Using procedures in functions
I found myself wishing to be able to call procedures inside a function today. My use case was to set up the arguments of an assert I planned to run in many different variations. I wanted to test mys implementation of human against the existing one and thought I'd write something like the following:
fn test_human(time: Time) = assert_eq(time -> human, time -> human_new)
fn test_human_range(times: List<Time>) = times |> map(test_human)
I think it would be very beneficial for testing if something like the first line at least was possible. The second line is probably a lot more involved, so I won't focus too much on it.
I imagine it might be difficult or undesirable to mix functions and procedures, in which case I would instead propose to introduce custom procedures, a function-like construct that can only call other procedures.
I found myself wishing to be able to call procedures inside a function today.
Yes, I can understand the pain. I also wanted something like this in the past.
On the other hand, that would complicate the language / type system a lot, I'm afraid. For now, function bodys are simply expressions. With your suggestion, we would allow (arbitrary) statements in the function body.
I imagine it might be difficult or undesirable to mix functions and procedures
Right.
in which case I would instead propose to introduce custom procedures, a function-like construct that can only call other procedures.
… or dare I say ... a macro? :smile:
Let's think about it!
I didn't even think about what I described in the end was basically just a macro. I would love for numbat to have a good macro system, but I think it takes quite a bit more thought than I originally imagined. For now, should I change the title and update the description to reflect that the issue will be about implementing macros?
For now, should I change the title and update the description to reflect that the issue will be about implementing macros?
Macros would be one way to support your use case. Let's also think about other ways. The title of the ticket is good as it is, thanks.
Hey, I'm late to the party sorry (but happy to be back)
I was wondering. What is the deal with procedures? Why not say they're not "magical" and are just normal functions that return nothing?
I guess we need a new type to express nothing like the unit type () in rust, bottom, nil, None`, or anything else.
I was wondering. What is the deal with procedures? Why not say they're not "magical" and are just normal functions that return nothing? I guess we need a new type to express nothing like the unit type
()in rust,bottom,nil,None`, or anything else.
That's a really good question actually. I hadn't thought about it and I don't know. I would have guessed that function purity could have something to do with it, but the datetime functions are impure and can be used normally. I think @sharkdp will have to weigh in on this one. I think this is a really good idea as long as there isn't something we are overlooking.
I was wondering. What is the deal with procedures? Why not say they're not "magical" and are just normal functions that return nothing? I guess we need a new type to express nothing like the unit type
()in rust,bottom,nil,None`, or anything else.
I think there is a lot of value in keeping functions pure (without any side effects). I think it makes a lot of sense for a language like Numbat to have a concept of functions that is close to the mathematical meaning of a function. For example, it would allow us to do lazy evaluation semantics (see Haskell) or to add memoization of function return values.
On the other hand, we already violated that property by introducing FFI functions like now() and random() that can be called from within functions. If we'd really like to go down the route of pure functions, we would have to introduce an effect system or higher-kinded types so we could use monads. I'm not sure if that would really be a win for Numbat users.