Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how do i pass a function type to a function #3943

Closed
lgphp opened this issue Jan 27, 2017 · 3 comments
Closed

how do i pass a function type to a function #3943

lgphp opened this issue Jan 27, 2017 · 3 comments

Comments

@lgphp
Copy link

lgphp commented Jan 27, 2017

i thiink pass a function to other function or method.but i dont't konw the function's prototype? i try pass a Pointer,but complier tell me function can't take address

def  fn1
  puts "test"
end
fn1_pointer = pointerof(fn1)

 def pass_fn( s )
    s.value
 end

pass_fn (fn1_pointer)

then, i change a way. i make the function to a String and invoke function recive a block,but how do i cover Strings to proc?

def test_m(x,y)
  puts x
  {x,y}
end

def exec_method(&block : Int32,String  ->  )
      block.call(3,"test")
end

def t_fn
  a = "test_m(Int32, String)"  
  proc_t = -> a #how do i excute a ?
  exec_method &proc_t   
end

i just think get as javascript's evel function.
thanks for you help~~~

@ysbaddaden
Copy link
Contributor

Questions about language design are better asked on stackoverflow: https://stackoverflow.com/tags/crystal-lang (they're not an issue).

Anyway, you can't assign or reference a function. You must use blocks instead.

They can be implicit (useful for immediate execution):

def call
  yield 3, "test"
end

call do |x, y|
  puts x
  {x, y}
end

Or explicit (useful to store callbacks for later use):

def call(block)
  block.call(3, "test")
end

fn = ->(x, y) {
  puts x
  {x, y}
}
call(fn)

Or explicitely captured:

def call(&block)
  block.call(3, "test")
end

call do |x, y|
  puts x
  {x, y}
end

@asterite
Copy link
Member

Actually, you can do it, you use -> followed by the function name:

def fn1
  puts "test"
end

def pass_fn(s)
  s.call # you use `call` to invoke it, because it will be a Proc
end

fn1_pointer = ->fn1 # This is how you do it
pass_fn (fn1_pointer)

If the function/method has arguments, you must specify their types:

def fn1(arg)
  puts arg * 2
end

def pass_fn(s)
  s.call(10)
end

fn1_pointer = ->fn1(Int32)
pass_fn (fn1_pointer)

You can also get a Proc from an instance method:

def pass_fn(s)
  puts s.call(/e/, "a")
end

string = "hello"
fn1_pointer = ->string.gsub(Regex, String)
pass_fn (fn1_pointer)

(though right now it won't work if it ends up being a dispatch)

However, I personally never use this feature because of the existence of blocks and anonymous functions, as @ysbaddaden mentions. This means we could decide to remove this feature before 1.0 (it simplifies the language)

(btw, it seems that syntax coloring with three backticks and cr stopped working, we now have to use the full crystal name... anyone has any idea what happened?)

@ysbaddaden
Copy link
Contributor

Oh. I never noticed that feature.

I vote to drop it. I don't think many people are aware of it, less using it; the syntax may be a little confusing (until you learn it), and it requires to specify argument types, whereas blocks usually don't have to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants