drym-org / qi

An embeddable flow-oriented language.
59 stars 12 forks source link

Fanout form should accept arbitrary Racket expressions #32

Closed countvajhula closed 2 years ago

countvajhula commented 2 years ago

It came up in the inaugural Design Challenge in the #qi room on Discord that fanout only accepts literals and not arbitrary Racket expressions (e.g. variables).

Example (working):

(define (compose-val N f)
  (flow (~> (clos f)
            (-< (gen N) _) ;; since (fanout N) only works when N is a literal
            fanout compose apply)))

We'd like it to also support:

(define (compose-val N f)
  (flow (~> (clos f)
            (fanout N) compose apply)))

This currently results in:

fanout: undefined;

(Pointed out by @benknoble)

benknoble commented 2 years ago

This syntax pattern is the reason that the fanout only accepts numbers. It is an efficient way to compile (fanout N) for literals, since the flow (-< _ …) is generated at "compile-time."

For a runtime strategy, maybe adding something like this could work? I haven't tried it:

…
[(_ ({~datum fanout} n:expr))
 #'(lambda args
     (apply values (apply append (build-list n (thunk args)))))]
…

AKA

…
[(_ ({~datum fanout} n:expr))
  ;; is this #'(flow (repeat-values n __)) ?
  ;; or maybe #'(flow (~>> (repeat-values n))) ?
  #'(lambda args (apply repeat-values n args))]
…

I think it could be useful to keep both patterns, then, so that you get the compile-time benefit for literals but runtime is still viable.

countvajhula commented 2 years ago

Fixed in #35