if a proc can be called like a function(i.e. with just parentheses and arguments, instead of a #call
method):
p = ->obj.method(T,U)
def func(foo : T -> U)
t = T.new(...)
b = foo(t) # instead of foo.call(t)
# ...
end
Shortening foo.call(t)
to foo(t)
make it more uniform (personally).This syntactic sugar is at most time comvenient, except only one ambiguration: If another method is also named foo
, then foo(t)
cannot differ between these calls. At that time, we can warn “ambigurous call with foo(t)
”,and require programmer to specify it as a method and a proc call.if not specified, it refers to the method foo.
Ruby has a similar syntactic sugar .()
,which is used like foo.(bar)
. it helps somehow,still different from a method call, I prefer using only one form of call.
3 Likes
Don’t we already have this with [ ]
? Pretty sure you can call a proc like
->(a, b){ a + b}[1, 2]
Proc#[]
is Ruby syntax, I tried to implement it in Crystal but I don’t think it works the same way – you can also get a pretty strange error message which might need to be put into an issue:
struct Proc
{% begin %}
def [](
{% for i in T.size %}
__arg{{i}} : {{T[i]}},
{% end %}
) : R
call(
{% for i in T.size %}
__arg{{i}},
{% end %}
)
end
{% end %}
end
echo = ->(text : String) { puts text }
echo["Hello world"]
This implementation doesn’t work because the macro expands statically where the generic arguments of Proc
are not bound. Essentially, you cannot write a def
that depends on the generic arguments.
But you can use the generic arguments as type restriction for the def’s parameters:
struct Proc(*T, R)
def [](*args : *T) : R
call(*args)
end
end
echo = ->(text : String) { puts text }
echo["Hello world"]
(this is exactly the same signature as Proc#call
btw.)
2 Likes