I have a PL terminology question about “first-order functions”: If I have a function f
that take one argument. That argument must be a top-level function and it is not a closure (i.e. no free-variables). For example, in C, it is just a function pointer. Is the function f
a “first-order function” or “higher order function”? Thanks.
@chansey97 As always, it depends on the exact definitions used. In Wikipedia (Higher-order function), they say:
So the function passed around is, well, just a function.
A function that accepts a function as an argument (or produces one as a result) is of higher order.
Other functions are first-order function.
Now, the question is whether “a pointer to a function” as in C counts as function.
I would say that conceptually a function is passed around, so I would call it a higher order function.
However the concept “first-class function” is also relevant. And since C doesn’t support anonymous functions (represented by closures), functions in C aren’t “first class”.
Thanks.
The reason why I have this question is: In order to compile a higher-order language (e.g. from lambda-calculus to machine code), there seems no necessary to defunctionalize higher-order functions to first order functions. Closure converting is enough.
If we say that a top-level (define (f x) (+ x 1))
is a way of defining first-order functions, then you can rewrite it to (define f (lambda (x) (+ x 1))
. If your compiler supports anonymous functions (and closures), then you don’t need a special case for compiling first-order functions.
I think - better get confirmation from one of the CS profs here.
I agree that if your target has higher-order functions (like C does) but no closures (like C doesn’t), then closure conversion is enough.
I was redescribing the question, but @mflatt already answer my question. Thanks!
I still paste my thought here (maybe some one feel interesting): What I mean is that if we have the following source program: (let ([f (if (eq? x #t)
(λ (y) (+ x 1))
(λ (y) (+ x 2)))])
(f 10))
There seem two ways to transform this program in the next pass. One way is hoisting + closure converting: (define (lambda-1 env y)
(+ (env-ref env 'x) y 1))
(define (lambda-2 env y)
(+ (env-ref env 'x) y 2))
(let ([f-clos (if (eq? x #t)
(make-closure lambda-1
(make-env `(x ,x)))
(make-closure lambda-2
(make-env `(x ,x))))])
(apply-closure f-clos 10))
(define (apply-closure clos v)
(let ((fun (closure-fun clos))
(env (closure-env clos)))
(fun env v)))
Another way is defunctionalizing: (struct lambda-1 (x) #:transparent)
(struct lambda-2 (x) #:transparent)
(let ([f-defun (if (eq? x #t)
(lambda-1 x)
(lambda-2 x))])
(apply-defun f-clos 10))
(define (apply-defun lam)
(match lam
[(lambda-1 x) (+ x 1)]
[(lambda-2 x) (+ x 2)]))
Note that the first one is still higher-order and the second one is first-order. Nevertheless, we still can compile the first one to machine code, as long as the target support GOTO and pointer. So machine code is essentially a high-order language.
for those using pollen, how come raco pollen render
doesn’t render <http://index.html.pm\|index.html.pm>
? I have to visit the url in order for it to render
IIRC, it renders fine for my project
Is there a way to control whether … and …+ are greedy using syntax-parse? A pattern I often like to use is prefix ... (some-literal args ...) suffix ...
but where I don’t want prefix to contain the more specific pattern. ~not can sort of work, but that can get verbose and is error prone (I also usually write macros so it handles most specific cases first and then falls through to more general ones for similar reasons).
Sort of like *? or +? with regular expressions.
can you confirm this? do: rm *.html
raco pollen reset
raco pollen render
raco pollen publish
and see if the published folder has index.html generated? for me it strangely just doesnt…
OHH WAIT, is index.html in your ptree?
@k has joined the channel