# Apply values to a procedure

**URL:** <https://racket.discourse.group/t/apply-values-to-a-procedure/3506>\
**Category:** Questions & Answers\
**Created:** [January 21, 2025, 5:15pm UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506 "2025-01-21T17:15:07Z")\
**Posts on this page:** 16\
**Page:** 2

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [January 26, 2025, 10:51am UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/21 "2025-01-26T10:51:43Z")

</div>

> [@countvajhula](#):
>
> Is `$bracket-apply$` a macro? If so, [this section of the docs](https://docs.racket-lang.org/qi/Language_Interface.html#%28part._.Using_.Racket_.Macros_as_.Flows%29) contains some recipes.

yes `$bracket-apply$` is a macro and i had a strange `bad syntax` error i did not understood but now i have registered it with `(define-qi-foreign-syntaxes $bracket-apply$)` it works:

```scheme
(define-qi-foreign-syntaxes $bracket-apply$)
(define Lplot (~> ((read-lines src)) list->vector {_[5 :]} vector->list (△ (~> string-split rest (△ string->number) vector)) ▽))

```

is parsed by SRFI 105 curly infix in :

```scheme
(define-qi-foreign-syntaxes $bracket-apply$)
    (define Lplot
      (~>
       ((read-lines src))
       list->vector
       ($bracket-apply$ _ 5 :)
       vector->list
       (△ (~> string-split rest (△ string->number) vector))
       ▽))

```

the critical point being `{_[5 :]}` parsed and converted in `($bracket-apply$ _ 5 :)`

i add too problem with infix parsing with macro, the problem being that you can manipulate a procedure like `+` or `list` but not a macro like `and` because you will get a `bad syntax` once evaluated outside the syntax for which it has been defined. The solution i found for manipulate macro is to use it like a syntax with syntax transformers. I do not know if Qi also use syntax transformers.

This day i tried to go further in associating Qi and infix parsing, i added for example `~>` to the list of my known operator having an operator precedence priority given by it position in the list:

in file: operators-list.rkt

```scheme
(define infix-operators-lst-for-parser-syntax

  (list
    exponential-operator-syntax
    (list #'* #'/ #'%)
    (list #'·) ; symbolic logic And
    (list #'⊕) ; symbolic logic Xor
    (list #'+ #'-)
	
    (list #'<< #'>>)

    (list #'& #'∣)

    (list #'< #'> #'= #'≠ #'<= #'>= #'<> #'equal?)

    (list #'and)

    (list #'or)

    (list #'~>)
    
    assignment-operator-syntax
    definition-operator-syntax 
    )

  )

```

it is necessary because this list use too being flatten just to know if a scheme symbol is an operator or another procedure.It is used in an `infix?` predicate to check if an expression is infix or prefix.

But when running the `$nfx$` of SRFI-105 i have a strange error related to Qi modification of the syntax i think. Note that it previously worked well for `$brackett-apply$` macro but not with `$nfx$`.

```scheme
(define-qi-foreign-syntaxes $nfx$) 
(define Lplot {((read-lines src)) ~> list->vector ~> {_[5 :]} ~> vector->list ~> (△ {string-split ~> rest ~> (△ string->number) ~> vector}) ~> ▽})

```

it is a bit hard to understand for someone not in the code of Scheme+ and SRFI-105.

`$brackett-apply$` is a macro called only when the parser meet some `[]`  
`$nfx$` is called when the parser meet an infix expression with need (or not depending of my code version) of applying an operator precedence rule when transforming the infix code in prefix sexpr.

On the previous code (sorry it is not simple expression) the code is pre-parsing this way:

```scheme
(define-qi-foreign-syntaxes $nfx$)
(define Lplot
      ($nfx$
       ((read-lines src))
       ~>
       list->vector
       ~>
       ($bracket-apply$ _ 5 :)
       ~>
       vector->list
       ~>
       (△ ($nfx$ string-split ~> rest ~> (△ string->number) ~> vector))
       ~>
       ▽))

```

i suppose the more nested `$nfx$` is first expanded, but this not important ; And i have this error:(a bit verbose i have activated debug info)

```scheme
Welcome to DrRacket, version 8.14 [cs].
Language: Determine language from source; memory limit: 8192 MB.
infix? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:16:39 -4>)
infix? : (a) allowed or not as infix ,check code
infix? : rv=#t
infix? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:16:39 -4>)
infix? : (a) allowed or not as infix ,check code
infix? : rv=#t
infix? : expr=()
infix? : null expr
infix? : rv=#t
infix? : expr=()
infix? : null expr
infix? : rv=#t
infix? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:23:46 -4>)
infix? : (a) allowed or not as infix ,check code
infix? : rv=#t
infix? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:23:46 -4>)
infix? : (a) allowed or not as infix ,check code
infix? : rv=#t
infix? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:24:75 4>)
infix? : (a) allowed or not as infix ,check code
infix? : rv=#t
infix? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:24:75 4>)
infix? : (a) allowed or not as infix ,check code
infix? : rv=#t
infix? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:29:55 4>)
infix? : (a) allowed or not as infix ,check code
infix? : rv=#t
infix? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:29:55 4>)
infix? : (a) allowed or not as infix ,check code
infix? : rv=#t
infix? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:32:38 5>)
infix? : (a) allowed or not as infix ,check code
infix? : rv=#t
infix? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:32:38 5>)
infix? : (a) allowed or not as infix ,check code
infix? : rv=#t
infix? : expr=()
infix? : null expr
infix? : rv=#t
infix? : expr=()
infix? : null expr
infix? : rv=#t
infix? : expr=(.#<syntax:Applications/Racket v8.14/share/pkgs/qi-lib/macro.rkt:87:47 v> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:17 string-split> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:30 ~>> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:33 rest> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:38 ~>> (.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:42 △> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:44 string->number>) .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:60 ~>> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:63 vector>)
infix? : check not start with an operator:#t
infix-rec? : expr=(.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:17 string-split> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:30 ~>> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:33 rest> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:38 ~>> (.#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:42 △> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:44 string->number>) .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:60 ~>> .#<syntax:opt/homebrew/var/www/drive/parsed_files_directory/displayTrajectory3D+.rkt:47:63 vector>)
infix? forbids: op1 without e1 : (not (null? (cdr expr))) :#t
infix? check (op1 e1 ...) : (member-syntax (car expr) oper-lst) : #f
infix? check not (op1 op2 ...) : (not (member-syntax (cadr expr) oper-lst)) :#f
infix? : rv=#f
. . ../../../../../../Users/mattei/Scheme-PLUS-for-Racket/nfx.rkt:41:2: pre-check-!*-generic-infix-parser : arguments do not form an infix expression :terms: '(#<syntax:/Applications/Racket v8.14/share/pkgs/qi-lib/macro.rkt:87:47 v> #<syntax:displayTrajectory3D+.rkt:47:17 string-split> #<syntax:displayTrajectory3D+.rkt:47:30 ~>> #<syntax:displayTrajectory3D+.rkt:47:33 rest> #<syntax:displayTrajectory3D...
> 

```

the main problem is that the Qi modified expression no more form an infix expression:

```scheme
. . ../../../../../../Users/mattei/Scheme-PLUS-for-Racket/nfx.rkt:41:2: pre-check-!*-generic-infix-parser : arguments do not form an infix expression :terms: '(#<syntax:/Applications/Racket v8.14/share/pkgs/qi-lib/macro.rkt:87:47 v> #<syntax:displayTrajectory3D+.rkt:47:17 string-split> #<syntax:displayTrajectory3D+.rkt:47:30 ~>> #<syntax:displayTrajectory3D+.rkt:47:33 rest> #<syntax:displayTrajectory3D...

```

**. ../../../../../../Users/mattei/Scheme-PLUS-for-Racket/nfx.rkt:41:2: pre-check-!\*-generic-infix-parser : arguments do not form an infix expression :terms: '(#\<syntax:/Applications/Racket v8.14/share/pkgs/qi-lib/macro.rkt:87:47 v\> #\<syntax:displayTrajectory3D+.rkt:47:17 string-split\> #\<syntax:displayTrajectory3D+.rkt:47:30 ~\>\> #\<syntax:displayTrajectory3D+.rkt:47:33 rest\>**

in fact the problem is that the Qi system has added this in front of my valid infix list expression:

**#\<syntax:/Applications/Racket v8.14/share/pkgs/qi-lib/macro.rkt:87:47 v\>**

is suppose `v` is a Qi macro or procedure used internally but as i'm modifying the syntax with syntax transformers after the pre-parsing of the reader and after the Qi modification of syntax my `infix?` predicate detect that the generated Qi expression is no more infix and it stop .

To be working my macros `$nfx$` should be applied before Qi modification, i read Qi is doing it like compilation but i do not know more.

The problem is a bit like macro phase, the order of modifying syntax here is important.

I do not know if there is something to do easily to fix that? i did not know how the Qi system works internally.

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [January 27, 2025, 5:06am UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/22 "2025-01-27T05:06:16Z")

</div>

I think you've correctly identified the problem. It has to do with the relationship between the reading and expansion stages, and the order of expansion.

The `$nfx$` macros are inserted into the user syntax at the _read_ stage, before we know anything yet about the _meaning_ of the program.

At the expansion stage, the way I look at it, syntax is transformed in relation to unspecified meaning. That is, expressions are transformed according to rules of the form, "this syntax means what that syntax means." The ultimate meaning of expressions is finally determined when the expressions are _evaluated_ after being expanded and compiled. Yet, the transformations during expansion are aware of meaning, at least in the sense that, unlike reading, expansion rules are _context sensitive_ (cf. [this great article](https://parentheticallyspeaking.org/articles/bicameral-not-homoiconic/) by Shriram).

At this expansion stage, to take context into account, macros are expanded "outside in." The outermost macros get to define the meaning of the contained syntax, delegating to any additional macros as needed by expanding to them. So even though the `$nfx$` is independently inserted at the reading stage in both places --- the outer one and the nested one --- when it gets to expansion, these are not expanded independently. Instead, the outer `$nfx$` expands first to generate the Qi expression. This expression is then expanded by Qi (specifically by the `flow` macro which specifies the Qi language). And finally, the inner `$nfx$` macro is expanded.

During the Qi expansion stage, if we don't tell Qi about `$nfx$`, it just assumes it is a function and uses it as a function (for example, it might try to `compose` it with other functions in the expansion). This, as you also mentioned encountering elsewhere, usually leads to a syntax error.

By using `define-qi-foreign-syntaxes`, we tell Qi to treat `$nfx$` as a "foreign" macro, that is, a form that isn't actually a function but has the same syntax as a function and is typically used as if it were a function. Racket's `and` is a good example of this (so much so, that people are usually confused when they find they can't use `and` in higher-order functions like `foldl`!).

So at this point, having been informed about `$nfx$`, Qi first transforms it for use as a flow. To do this, it rewrites the `$nfx$` expression by [adding a wrapping lambda](https://github.com/drym-org/qi/blob/3f63f9ce77231dffec14cbd7ab7d063899d9e988/qi-lib/macro.rkt#L90) taking a single `v` argument that is then passed to the original macro --- basically just wrapping the macro so it can be used as a function.

And finally, expansion is now delegated to the inner `$nfx$` macro. But of course, at this stage, the expression has already been rewritten in a way that can't then be parsed correctly by the `$nfx$` macro. That is,

```scheme
($nfx$ string-split ~> rest ...)

```

has become:

```scheme
(lambda (v)
  ($nfx$ v string-split ~> rest ~> ...))

```

… as you observed!

The issue is that, unlike `and`, but more like `let`, `$nfx$` is a Racket macro that _doesn't_ have the same syntax as function application and doesn't behave like a function. So it can't be treated as a [_flow_](https://docs.racket-lang.org/qi/Principles_of_Qi.html#%28part._.What_is_a_.Flow_%29) by using `define-qi-foreign-syntaxes`.

Regarding a solution, one option is to wrap the inner infix expression with [`(esc ...)`](https://docs.racket-lang.org/qi/Qi_Forms.html#%28form._%28%28lib._qi%2Fmain..rkt%29._esc%29%29). This tells Qi that what follows is a Racket expression, and so it will not attempt to expand it.

Another way could be to write a `$nfx$` [_Qi_ macro](https://docs.racket-lang.org/qi/Qi_Macros.html) using `define-qi-syntax-rule`, which expands to an appropriate use of the `$nfx$` _Racket_ macro, so that, in a way, at the point where Qi is about to rewrite the `$nfx$` macro, you get to take back control of expansion at that point. In fact, the previous solution is also similar, where instead of taking control back yourself, you give control to Racket, which is good because `$nfx$` is a _Racket_ macro, after all.

Possibly one simple way to write this Qi macro is just:

```scheme
(define-qi-syntax-rule ($nfx$ e ...)
  (esc ($nfx$ e ...)))

```

I suspect this will work precisely because the `$nfx$` was inserted at the reading stage in a _context-free_ way, so that it doesn't refer to a specific binding (e.g., the Racket macro `$nfx$`), and the same `$nfx$` syntax could refer to either the Qi macro or the Racket macro when the bindings are resolved at expansion time. I could be wrong, though!

If this approach works out, then it could be worth making an adapter library for curly infix syntax and Qi, which defines the necessary adapter macros like `$nfx$` as Qi macros.

If you have any other ideas or thoughts (or if we need to debug further), you're welcome to stop by at the next (or any) Qi meetup, which [happens on Fridays](https://racket.discourse.group/t/racket-events-calendar/2173) 🙂

---

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [January 28, 2025, 11:14am UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/23 "2025-01-28T11:14:11Z")

</div>

> [@countvajhula](#):
>
> [this great article](https://parentheticallyspeaking.org/articles/bicameral-not-homoiconic/)

Your message and the article is very interesting, i will explain how the curly infix parser works too. There are many stage:

1-file is parsed "lexically" character by character to construct the tokens and also the tree of sexpr i think (code was part of SRFI 105, i just modified it)  
At this stage too the `$nfx$` and `$bracket-apply$` are inserted. But also some simple infix code expressions without operator precedence need is already converted in prefix code .Expressions are not evaluated but "quoted".  
This is donne by `#lang reader SRFI-105` or by externally by the same scheme code in a program called `curly-infix2prefix4racket.rkt` .

2-the previous code is passed to Scheme/Racket , then the macros `$nfx$` and `$bracket-apply$` (that are in Scheme+) are expanded , at this point this could conflict with Qi own macro expansion. Note that my macro use syntax transformers, `with-syntax`, manipulate syntax, not quoted expressions (there is no problem to manipulate macro so)

If there was no need of operator precedence it works because there is no `$nfx$` inserted.

A few thoughts about Qi system:

> [@countvajhula](#):
>
> To do this, it rewrites the `$nfx$` expression by [adding a wrapping lambda](https://github.com/drym-org/qi/blob/3f63f9ce77231dffec14cbd7ab7d063899d9e988/qi-lib/macro.rkt#L90) taking a single `v` argument that is then passed to the original macro --- basically just wrapping the macro so it can be used as a function.

> [@countvajhula](#):
>
> And finally, expansion is now delegated to the inner `$nfx$` macro. But of course, at this stage, the expression has already been rewritten in a way that can't then be parsed correctly by the `$nfx$` macro. That is,
> 
> ```scheme
> ($nfx$ string-split ~> rest ...)
> 
> ```
> 
> has become:
> 
> ```scheme
> (lambda (v)
> ($nfx$ v string-split ~> rest ~> ...))
> 
> ```
> 
> … as you observed!

at this point i do not understand how it could work with **any** macro because Qi has **changed the number and place of arguments** of the macro.

It would be better that Qi manipulate just the syntax with syntax transformers to keep the correct syntax of any existing macro and this will solve the procedure vs macro problem.

Also if i understand that we can encapsulate a macro in a procedure to be able to use it in a `map` or `foldr` ,the resulting procedure is not equivalent to the macro , for example the short-circuited `and` macro is no more short-circuited when encapsulated in a procedure/lambda because at some point we pass the argument to the procedure/lambda and they are immediatly evaluated.

A possibly workaround about that is for me to modify again the SRFI 105 code to make apply the `$nfx$` in phase 1, then the Racket/Qi system will only saw normal already prefixed expression but this has some drawback:

-delegate much work to external parser or reader  
-duplicate a lot of procedures (even if they already are generic sometimes) to work not with syntaxified expressions but quoted ones  
-not easy possibility to add dynamically new operators with a special precedence order...

> [@countvajhula](#):
>
> Possibly one simple way to write this Qi macro is just:
> 
> ```scheme
> (define-qi-syntax-rule ($nfx$ e ...)
> (esc ($nfx$ e ...)))
> 
> ```

with this code:

```scheme
(define-qi-syntax-rule ($nfx$ e ...)
	    (esc ($nfx$ e ...)))

(define Lplot {(tdl) ~> vector->list ~> (△ {string-split ~> rest ~> (△ string->number) ~> vector}) ~> ▽})

```

it is parsed in:

```scheme
(define-qi-syntax-rule ($nfx$ e ...) (esc ($nfx$ e ...)))
(define Lplot
      ($nfx$
       (tdl)
       ~>
       vector->list
       ~>
       (△ ($nfx$ string-split ~> rest ~> (△ string->number) ~> vector))
       ~>
       ▽))

```

but i get an error :

```scheme
Welcome to DrRacket, version 8.14 [cs].
Language: Determine language from source; memory limit: 8192 MB.
~>: bad syntax in: (~> string-split rest (△ string->number) vector)

```

with more info for debug:

 ![Capture d’écran 2025-01-28 à 12.10.55](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/6/66ea27e73dd872966f0b49226cb789190a8db53f.jpeg)

 ![Capture d’écran 2025-01-28 à 12.17.16](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/e/eb675f957a0ef99b3130071ab6cf5ef8fc2b228e.jpeg)

note: post updated many times due to typos

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [January 28, 2025, 7:28pm UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/24 "2025-01-28T19:28:12Z")

</div>

> at this point i do not understand how it could work with **any** macro because Qi has changed the number and place of arguments of the macro.

For a moment assuming that `and` is Racket's usual `and` macro, `(~> (a) (and b c))` rewrites to a use of `(and a b c)`. In fact, you could also do these variations:

```scheme
(~>> (c) (and a b))
(~> (a c) (and _ b _))

```

These are all equivalent to `(and a b c)`. If this is the expression you intended to write, the above variations are just different ways to write it.

(Note: in reality, `and` is a Qi form that is equivalent to Racket's `conjoin` so it can't be used this way --- but for the purpose of discussion, I can't think of any other examples of Racket macros that we might want to use in a flow!)

> Also if i understand that we can encapsulate a macro in a procedure to be able to use it in a `map` or `foldr` ,the resulting procedure is not equivalent to the macro , for example the short-circuited `and` macro is no more short-circuited when encapsulated in a procedure/lambda because at some point we pass the argument to the procedure/lambda and they are immediatly evaluated.

You're right that there are short-circuiting implications, but can you think of any cases where they would be surprising in practice? Note that in the above examples, the argument is always evaluated, but the other expressions in the `and` form are shortcircuited as usual. When used in a threading flow, you would usually expect that the threaded arguments are evaluated, so this shouldn't be surprising. The main effect of the lambda isn't to prevent shortcircuiting but to delay evaluation.

With `foldr` and `foldl`, as they are functions and as they expect a function in the higher order position, I'm not sure there is any way to get shortcircuiting with them. But if you feel this kind of shortcircuiting fold would be a useful feature, we could consider adding it to [Qi's `foldl` and `foldr`](https://docs.racket-lang.org/qi/List_Operations.html) in some form (ideas welcome!).

> with more info for debug:

That's helpful! Well, at present I'm not sure if defining a Qi macro to simplify the integration is straightforward, due to the somewhat complicated interaction between the read and expand stages, but what if you try just using `esc` on its own? Something like:

```scheme
(define Lplot {(tdl) ~> vector->list ~> (△ (esc (lambda (v) {(v) ~> string-split ~> rest ~> (△ string->number) ~> vector}))) ~> ▽})

```

If this works, it should provide a starting point to understanding how the Qi macro might work. We need something that rewrites the resulting use of `$nfx$` so that it correctly introduces the implicit argument (we can assume a single argument to start with). Something like this:

```scheme
(define-qi-syntax-rule ($nfx$ e0 op e ...)
  (esc (lambda (v) ($nfx$ (v) op e0 op e ...)))

```

I'm not too familiar with the syntax of `$nfx$` so I'm not sure if this is quite right. But _some_ variation of this might work if we can at least get it syntactically to look right. I'm also still concerned about the fact that the curly infix transformations occur prior to expansion (and it sounds like, maybe even prior to the reading stage?). So in that case, there might be some issues with introducing the binding `op` here during expansion, as at the expansion stage it refers to a specific binding and is not just an identifier. But it's worth trying.

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [January 28, 2025, 9:54pm UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/25 "2025-01-28T21:54:41Z")

</div>

A short note on short-circuiting 😉

I frequently use a pattern like `(flow (~> … do some work … (and _ more-work)))` where the previous operations are fallible, and `more-work` should only get invoked if the previous work succeeded. For example:

```scheme
(define ability (~> (mg) monster-group-set-name (hash-ref ads _ #f) (and _ ability-decks-current)))

```

If the `hash-ref` doesn't succeed, I don't want to do `ability-decks-current`. So you can still short-circuit anything in the `and` directly, but any values flowing to it must have already been evaluated. (You could delay them yourself if needed by making them thunks and then doing `(and … apply …)`, but I can't come up with a realistic example.)

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [January 28, 2025, 10:24pm UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/26 "2025-01-28T22:24:07Z")

</div>

At first when I saw your code, I thought you were doing some elaborate computations on the [monster group](https://en.wikipedia.org/wiki/Monster_group) and was frightened.

But of course it must be [Frosthaven](https://github.com/benknoble/frosthaven-manager/) 😄

---

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [January 29, 2025, 10:44pm UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/27 "2025-01-29T22:44:25Z")

</div>

> [@countvajhula](#):
>
> Note: in reality, `and` is a Qi form that is equivalent to Racket's `conjoin` so it can't be used this way -

oh ... i perheaps misunderstand what is really a flow, seems the `and` of flows is not really the `and` of scheme... 🤔

But i will continue learning Qi and the more concrete example i will get will be the best.

> [@countvajhula](#):
>
> For a moment assuming that `and` is Racket's usual `and` macro, `(~> (a) (and b c))` rewrites to a use of `(and a b c)`. In fact, you could also do these variations:
> 
> ```scheme
> (~>> (c) (and a b))
> (~> (a c) (and _ b _))
> 
> ```

so it is short-circuited , it is normal to have at least the first argument evaluated

> [@countvajhula](#):
>
> Something like:
> 
> ```scheme
> (define Lplot {(tdl) ~> vector->list ~> (△ (esc (lambda (v) {(v) ~> string-split ~> rest ~> (△ string->number) ~> vector}))) ~> ▽})
> 
> ```
> 
> If this works, it should provide a starting point to understanding how the Qi macro might work.

yes ,it worked 👍

but it force the coder to adapt its code to Qi for this reason i prefer the solutions that follow.... i prefer trying to modify our libraries to make them enought tolerant to be used simply.

> [@countvajhula](#):
>
> I'm not too familiar with the syntax of `$nfx$` so I'm not sure if this is quite right.

The job of `$nfx$` is simply to take an infix expression and convert it in prefix. So it is something like:

```scheme
(define-syntax $nfx$
  (lambda (stx)
    (syntax-case stx ()

       .............

          (($nfx$ e1 op1 e2 op ...)
       
	          (with-syntax
           ...............

```

where e1 op1 e2 op ... are the argument.

For example `{3 * 5 + 2}` my favorite example test 🙂 is transformed in prefix by a call to `($nfx$ 3 * 5 + 2)` and will generate something like i expect: `(+ (* 3 5) 2)` .

This is a simplification because i added, more and more support for both infix and prefix and math expression in the next release and the code is becoming hard and perheaps i should refactor some thing.

for example there is not only a simple case but many depanding of the number of args:

```scheme
(define-syntax $nfx$
  (lambda (stx)   
    (syntax-case stx ()

      (($nfx$ expr) 

       (with-syntax
			 
	   ((parsed-args
....

(($nfx$ op1 e1) 

       (with-syntax
			 
	   ((parsed-args

.........
(($nfx$ e1 op1 e2 op ...)
       
	 (with-syntax 
			 
	     ((parsed-args

......

```

[source code of `$nfx$`](https://github.com/damien-mattei/Scheme-PLUS-for-Racket/blob/main/nfx.rkt#L39)  
Perheaps i should use a macro taking simply a list as arguments but thinking of that will create problems i think.

> [@countvajhula](#):
>
> I'm also still concerned about the fact that the curly infix transformations occur prior to expansion (and it sounds like, maybe even prior to the reading stage?).

yes and no, it was the case in first versions where i just use SRFI 105 strict but it appeared SRFI 105 was a good idea but just the start of the problem of dealing with infix expression because it does not take in account operator precedence, for example in strict SRFI 105 `3 * 5 + 2` should be written `{{3 * 5} + 2}` , so there is the same number of parenthesis than with sexpr, also different parenthesis, not a big deal !  
SRFI 105 was great for expression with the same operator such as `{1 + 2 + 3 + 4}` because it transformed it in `(+ 1 2 3 4)` ,great ! 🙂

And it was perfect for `{(x) ~> expr1 ~> expr2 ~> expr3}` which works when i reactivate the strict SRFI 105 mode of the parser.

But the latest version of my code SRFI-105/Scheme+ now allow using `( )` inside `{ }` as mathematic parenthesis, so the code has again changed evolved and then some expression as `{(x) ~> expr1 ~> expr2 ~> expr3}` no more works because `$nfx$` is now inserted in the expressions and convert it in prefix not the same way the original SRFI 105 did it.

> [@countvajhula](#):
>
> We need something that rewrites the resulting use of `$nfx$` so that it correctly introduces the implicit argument (we can assume a single argument to start with). Something like this:
> 
> ```scheme
> (define-qi-syntax-rule ($nfx$ e0 op e ...)
> (esc (lambda (v) ($nfx$ (v) op e0 op e ...)))
> 
> ```

this worked again 😮 👍

but i'm a bit surprised because your macro use `op e0 op ` but my infix macro `$nfx$` as we see it use `op1 e2 op` , i mean the operators are not the same but it worked even if my op1 and op are differents 😮

but for this reason i wrote another macro like this :

```scheme
  (define-qi-syntax-rule ($nfx$ e0 op other ...)
	    (esc (lambda (v) ($nfx$ (v) op e0 other ...))))

```

that worked too.

i can not decide which macro to choose in the definitive version of my code, as the 2 seems to work?

i tested those macros with this code:

```scheme
{Lplot := (tdl) ~> vector->list ~> (△ (string-split ~> rest ~> (△ string->number) ~> vector)) ~> ▽}

```

note `:=` is like `set!` scheme , like `<-` too

this code is translated by the parser at step 1 in :

```scheme
($nfx$
     Lplot
     :=
     (tdl)
     ~>
     vector->list
     ~>
     (△ (string-split ~> rest ~> (△ string->number) ~> vector))
     ~>
     ▽)

```

and at step 2 , what you probably call expansion stage in:

 ![Capture d’écran 2025-01-29 à 23.18.03](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/e/e4bf59ee4a49eb7a21b1f540c7a86e91c64fcd16.jpeg)

but it was not so easy to get this result, i have to insert more the `~>` operator in my code for a silly reason: SRFI 105 was great to parse infix with same operator, but now i have `:=` and `~>` it required a precedence rule to apply and also the code with `~>` was translated in some thing like `(~> (~> (~> (e1)) e2) e3)` (it is an example, not sure of the exact syntax as the code is correct now) which is a valid sexpr but was not compatible with the Qi flow syntax. It generated the famous `bad syntax` i did not understood ,it was in fact nothing related to Qi but with my parser not simplifying left (?) associative n-arity sexpr.

so i changed my code to get a result like `(~> (e1) e2 e3)` which is compatible with Qi.

It was not hard to fix but as the code is complex i have to change and modify those things to add the FLOW support:

operators.rkt:

```scheme
(define (FLOW-op? oper)
  (datum=? oper '~>))

(define (is-associative-operator? op)
  (or (AND-op? op)
      (OR-op? op)
      (XOR-op? op)
      (EQUIV-op? op)
      (ADD-op? op)
      (MULTIPLY-op? op)
      (FLOW-op? op)
      (DEFINE-op? op)
      (ASSIGNMENT-op? op)))

(define (isFLOW? expr)
  (and (pair? expr) (FLOW-op? (operator expr))))

```

n-arity.rkt:

```scheme
;; return a closure of collect-leaves function associated with an operator (AND or OR or others)
(define (make-collect-leaves-operator oper)

  ;;(display "make-collect-leaves-operator") (newline) 
  (let ((ourOperation?
	 
	 (cond
	  
	  ((AND-op? oper) isAND?)
	  ((OR-op? oper) isOR?)
	  ((ADD-op? oper) isADD?)
	  ((DEFINE-op? oper) isDEFINE?)
	  ((ASSIGNMENT-op? oper) isASSIGNMENT?)
	  ((FLOW-op? oper) isFLOW?)

	  (else ; fonction generique pour tous les operateurs ( non syntaxiques )
	   (lambda (expr) (and (pair? expr) (equal? (car expr) oper)))))))

    
    (letrec ((collect-leaves-operator

	      (lambda (expr)
		(cond
		 ((not (list? expr)) (list expr)) ;; symbol,number,boolean,vector,hash table....
		 ((null? expr) (list expr))
		 ((function-without-parameters? expr) (list expr))
		 ((unary-operation? expr)
		  (list
		   (cons
		    (operator expr)
		    (list (n-arity (arg expr))))))
		 ((ourOperation? expr) ;; #;(eqv? oper (operator expr))
		  (apply append (map collect-leaves-operator (args expr))))
		 (else (list (n-arity expr)))))))

        collect-leaves-operator)))) ; end module

```

and in `$nfx$` :

```scheme
(if ;;(not (isEXPONENTIAL? expr))
		    (or (isDEFINE? expr)
		       (isASSIGNMENT? expr)
			   (isFLOW? expr))
		    ;; make n-arity for <- and <+ only (because could be false with ** , but not implemented in n-arity for now)

```

i have inserted those change for the next release of Scheme+/SRFI-105 to be compatible with Qi `~>`.

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [January 31, 2025, 3:55am UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/28 "2025-01-31T03:55:28Z")

</div>

> i have inserted those change for the next release of Scheme+/SRFI-105 to be compatible with Qi `~>` .

Cool stuff! 👍

> it appeared SRFI 105 was a good idea but just the start of the problem of dealing with infix expression because it does not take in account operator precedence

> i added, more and more support for both infix and prefix and math expression in the next release and the code is becoming hard and perheaps i should refactor some thing.

[Rhombus supports infix operators](https://docs.racket-lang.org/rhombus-reference/ref-operator.html#%28def._%28%28submod._%28lib._rhombus%2Fprivate%2Famalgam..rkt%29._core%29._operator._rhombus%2Fdefn%29%29) and allows you to indicate precedence. Maybe there's some inspiration to be found there?

> that worked too.  
> i can not decide which macro to choose in the definitive version of my code, as the 2 seems to work?

In your example, you have one main wrapping `{}` for the whole expression, but the inner expression in `(△ ...)` _isn't_ in curly braces:

```scheme
{Lplot := (tdl) ~> vector->list ~> (△ (string-split ~> rest ~> (△ string->number) ~> vector)) ~> ▽}

```

So in this case, I suspect the inner expression never gets wrapped with `$nfx$`, and so, the Qi macro we've written never gets invoked! Assuming the outer `$nfx$` traverses the full syntax and changes all infix expressions to prefix, it should work correctly as is, without needing the Qi macro.

Do you anticipate ever using curly brackets in an expression nested within a flow?

If you do, the curly expression would insert `$nfx$` there, and in that case, as it is considered a Qi expression, the Qi macro would be invoked. The macro we've written translates the expression into an escaped Racket `$nfx$` expression, delegating control back to Racket and to the `$nfx$` macro, for processing as usual.

At this point, I would expect in your version of the macro that `{f ~> g ...}` would become `(lambda (v) ($nfx$ (v) ~> f g ...))`, so it would likely complain that `($nfx$ (v) ~> f g ...)` isn't a valid infix expression since there is no `~>` between `f` and `g`.

Also note the distinction between [Qi's `~>` form](https://docs.racket-lang.org/qi/Qi_Forms.html#%28part._.Routing%29), and its [embedding](https://docs.racket-lang.org/qi/Qi_Macros.html#%28part._.Embedding_a_.Hosted_.Language%29) into Racket that's [also named `~>`](https://docs.racket-lang.org/qi/Language_Interface.html#%28part._.Threading%29). In our Qi macro here, we are rewriting to the _Racket_ version, hence the initial form that passes the arguments (the Qi version does not mention any arguments). We do this so that `$nfx$` is processed as an ordinary Racket expression, the way that was intended by you when you wrote the macro.

Technically, as you pointed out earlier, if we could only give control to `$nfx$` _before_ Qi parses the expression, then there would be no problems. For that matter, it should be the same with any macro, like this example:

```scheme
(require syntax/parse/define)

(define-syntax-parser bool
  [(_ ((~datum &&) a b)) #'(and a b)]
  [(_ ((~datum ||) a b)) #'(or a b)])

(bool (&& 1 2))

```

If we try to use `&&` as an infix operator as `(bool {1 && 2})`, then I suspect this macro would issue (the famous) `bad syntax` error, because the `bool` macro gets control of expanding the expression, but it doesn't know what to do with `$nfx$`. And unlike Qi where we are able to get "inside" the language using macros, there's no way to recover from this in this `bool` macro.

But I am not aware of a way in Racket to indicate that one macro has precedence over others. In fact, this would probably not be sound in general since there could be macros that _do_ define an expansion for `($nfx$ ...)`, and it could cause an error if it is handled as an infix expression.

Racket's expansion rule is that syntax is expanded outside-in, and within this paradigm, we need to tell the outer macro how to handle the inner macro, even if just to say, as we are doing here with Qi, please do nothing, I promise I'll take care of it later 🙂

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [January 31, 2025, 4:36am UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/29 "2025-01-31T04:36:19Z")

</div>

> [@countvajhula](#):
>
> Technically, as you pointed out earlier, if we could only give control to `$nfx$` _before_ Qi parses the expression, then there would be no problems. For that matter, it should be the same with any macro, like this example:
> 
> …
> 
> But I am not aware of a way in Racket to indicate that one macro has precedence over others. In fact, this would probably not be sound in general since there could be macros that _do_ define an expansion for `($nfx$ ...)`, and it could cause an error if it is handled as an infix expression.
> 
> Racket's expansion rule is that syntax is expanded outside-in, and within this paradigm, we need to tell the outer macro how to handle the inner macro, even if just to say, as we are doing here with Qi, please do nothing, I promise I'll take care of it later 🙂

Is there a reason `local-expand` doesn't work in this context? (I haven't read this whole thread in detail, and I also haven't used Qi, so this may be an obvious question.)

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [January 31, 2025, 5:07am UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/30 "2025-01-31T05:07:57Z")

</div>

I think that would require the `bool` macro, in the above example, to proactively `local-expand` the `$nfx$` macro after requiring it from the Scheme+ library?

I believe Damien needs the `$nfx$` macro to transform the source code without requiring cooperation from third party macros, as it is intended to be a general way to write expressions using infix syntax.

To summarize the case as I understand it: `$nfx$` is inserted prior to expansion by rewriting all uses of `{}` in the source file to `($nfx$ ...)`, and `$nfx$` is an ordinary macro invoked at expansion time. In cases where `{}` happened to be present inside uses of macros in the source file, can these `($nfx$ ...)` forms be expanded by the `$nfx$` macro first before the containing macros get the result?

---

<div class="post-metadata">

**Author:** ![jgomo3](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/jgomo3/32/496_2.png) [@jgomo3](https://racket.discourse.group/u/jgomo3)\
**Post date:** [January 31, 2025, 5:47pm UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/31 "2025-01-31T17:47:34Z")

</div>

A bit late to the party.

An alternative:

```scheme
(call-with-values (curry values 1 2 3) list)

```

---

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [January 31, 2025, 6:20pm UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/32 "2025-01-31T18:20:14Z")

</div>

> [@countvajhula](#):
>
> In your example, you have one main wrapping `{}` for the whole expression, but the inner expression in `(△ ...)` _isn't_ in curly braces:
> 
> ```scheme
> {Lplot := (tdl) ~> vector->list ~> (△ (string-split ~> rest ~> (△ string->number) ~> vector)) ~> ▽}
> 
> ```
> 
> So in this case, I suspect the inner expression never gets wrapped with `$nfx$`, and so, the Qi macro we've written never gets invoked! Assuming the outer `$nfx$` traverses the full syntax and changes all infix expressions to prefix, it should work correctly as is, without needing the Qi macro.

yes 😮 no recall to `$nfx$` because there is a `map` recursively on the sub-sexpr and we all know we can not `map` with a macro so it is [a different procedure](https://github.com/damien-mattei/Scheme-PLUS-for-Racket/blob/main/infix-with-precedence-to-prefix.rkt#L358) (note there is 3 version: github, running for application, and developped for future release, the link is not exactly the one that run on my host but the `map` is in every versions ) used :

```scheme
 (define deep-terms (map (lambda (x) (recall-infix-parser x operator-precedence creator)) terms))

```

yes in the latest version of Scheme+ the inner ( ) are treated as infix. Which could be source of problem ,consider `(cons + L)` ,is it a prefix one (for sure) but the parser will think it is the addition of cons and L 😬 (you can only avoid,it at user leve by (define add +) and do (cons add L) the next version will `eval`luate (with limited problems described in the great article you where referring previously) `cons` to find it in the scheme basename library , but again this is not fully reliable, think of (f ° g) with f and g user level procedure not known from basename lib and ° an operator (used infix here) of functions composition.... next release should try to fix all this the better way. But note that having both prefix and infix this way create what is called an 'ambiguous language' 😏 .

Yes in the linked code above there is just next this :

```scheme
;;(display "!*prec-generic-infix-parser : rv : deep-terms:") (display deep-terms) (newline)
      ;; test for simple-infix (no operator precedence)
      (if (simple-infix-list-syntax? deep-terms)
	  (begin
	    ;;(display "!*prec-generic-infix-parser : deep-terms is a simple infix list") (newline)
	    ;;(display "!*prec-generic-infix-parser : deep-terms=") (display deep-terms) (newline)
	    (list ; cadr is op in arg1 op arg2 op ....
	     (cons (cadr deep-terms) (alternating-parameters deep-terms)))) ; we put it in a list because nfx take the car...

	  (begin
	    ;;(display "!*prec-generic-infix-parser : deep-terms is not a simple infix list") (newline)
            (pre-check-!*-generic-infix-parser deep-terms ;terms
						operator-precedence
						creator)))))

```

so when there is some simple infix (with same operator) as in the nested flow of example it is put in the good syntax by the first branch of the `if` :

```scheme
(list ; cadr is op in arg1 op arg2 op ....
	     (cons (cadr deep-terms) (alternating-parameters deep-terms))

```

else we apply the parser again:

```scheme
(pre-check-!*-generic-infix-parser deep-terms ;terms
						operator-precedence
						creator)

```

as the operator is taken from `(cadr deep-terms)` it works for every operator ,even for those that were not in the list like `~>` , the new flow operator. (and even for non (left) associative operator wich could result in unknow result..... i shoud add a test in this code)

> [@countvajhula](#):
>
> Also note the distinction between [Qi's `~>` form](https://docs.racket-lang.org/qi/Qi_Forms.html#%28part._.Routing%29), and its [embedding](https://docs.racket-lang.org/qi/Qi_Macros.html#%28part._.Embedding_a_.Hosted_.Language%29) into Racket that's [also named `~>`](https://docs.racket-lang.org/qi/Language_Interface.html#%28part._.Threading%29).

🤔 🤔 🤔 sure i do not well understand the differences, the arguments are not the same , so i suppose any misunderstanding and misuse by me is important indeed.....

> [@countvajhula](#):
>
> Do you anticipate ever using curly brackets in an expression nested within a flow?

yes, i understand the problem is that Qi dislike macro in flow , forbids perheaps, unless rewritten in Qi special macro syntax....

But there is no need of macro nested like `$nfx$` as i can use ( ) in prefix expression too instead of { } now , the problem is when indexing object with [] that is converted in another macro `$brackett-apply$` which is used with vector, arrays,strings, hash tables.....

Note that there is really no more concern with nested `$nfx$` because as this macro recurse deeply on the sexpr tree you can parse a whole procedure with `define-infix` and in the future i should wrote an equivalent for a whole module parsing....

> [@countvajhula](#):
>
> Do you anticipate ever using curly brackets in an expression nested within a flow?

i made a lot of test, for example this works :

```scheme
(define Lplot {(src) ~> read-lines ~> list->vector ~> (vector-copy _ 5) ~> vector->list ~> (△ {string-split ~> rest ~> (△ string->number) ~> vector}) ~> ▽})

```

without no need of `define-qi-syntax-rule` but this do not:

```scheme
(define-qi-syntax-rule ($nfx$ e0 op other ...)
	    (esc (lambda (v)
	  	   (display "In $nfx$ e0 op other of define-qi-syntax-rule") (newline)
	  	   ($nfx$ e0 op other ...))))

(define Lplot {(src) ~> read-lines ~> list->vector ~> (vector-copy _ 5) ~> vector->list ~> (△ {string-split ~> rest ~> (△ string->number) ~> vector}) ~> ▽})

```

it expands in:

```scheme
(define Lplot
      ($nfx$
       (src)
       ~>
       read-lines
       ~>
       list->vector
       ~>
       (vector-copy _ 5)
       ~>
       vector->list
       ~>
       (△ ($nfx$ string-split ~> rest ~> (△ string->number) ~> vector))
       ~>
       ▽))

```

and after:

 ![Capture d’écran 2025-01-31 à 18.30.03](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/1/13390569498a5e9584d56cfff0034a2aea26c6c7.jpeg)

but it works with your macro that i still do not understand...

```scheme
(define-qi-syntax-rule ($nfx$ e0 op e ...)
	    (esc (lambda (v)
	  	   (display "In $nfx$ e0 op e of define-qi-syntax-rule") (newline)
	  	   ($nfx$ (v) op e0 op e ...))))

```

 ![Capture d’écran 2025-01-31 à 18.38.27](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/8/8360a25e3e7aac130ac03f4fa36838828d6e95c8.png)

 ![Capture d’écran 2025-01-31 à 18.38.49](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/6/6dcb534df10038666a554a09c337014b9cfc84cc.png)

```scheme

.........

In $nfx$ e0 op e of define-qi-syntax-rule
In $nfx$ e0 op e of define-qi-syntax-rule
In $nfx$ e0 op e of define-qi-syntax-rule
In $nfx$ e0 op e of define-qi-syntax-rule
In $nfx$ e0 op e of define-qi-syntax-rule
In $nfx$ e0 op e of define-qi-syntax-rule
In $nfx$ e0 op e of define-qi-syntax-rule
In $nfx$ e0 op e of define-qi-syntax-rule
In $nfx$ e0 op e of define-qi-syntax-rule
In $nfx$ e0 op e of define-qi-syntax-rule
after Lplot
Lplot length=1440
Lplot=
(#(-5.226162 -0.133805 1.462782) #(-5.239695 -0.133871 1.446325) #(-5.253049 -0.133932 1.429818) #(-5.266226 -0.133988 1.413263) #(-5.279225 -0.134038 1.396661) #(-5.292047 -0.134083 1.380013) #(-5.304692 -0.134123 1.363318) #(-5.317161 -0.134158 1.346578) #(-5.329453 -0.134187 1.329793) #(-5.34157 -0.134211 1.312965) #(-5.353512 -0.13423 1.296094) #(-5.365279 -0.134243 1.279181) #(-5.376871 -0.134252 1.262226) #(-5.388289 -0.134255 1.24523)

.......

```

`$nfx$` is not a problem as i can parse a whole procedure ,module or even file with a single initial call to `$nfx$` and as you said it the macro expand from outside-in or even i can use your mysterious macro.

The concern about [] ,alias `$brackett-apply$` ,you perheaps noticed that i replace the macro with a scheme procedure `(vector-copy _ 5)` because this won't works: `_[5 :]` as it is transformed in a macro : `($brackett-apply$ _ 5 :)` ,note this is a slicing notation such as the one in Python.

here is my definition of `$bracket-apply$` :

```scheme
;; > (define x 1)
;; > ($bracket-apply$ (vector 0 1 2 3 4) 2 + x)

;; bracket-apply : #'parsed-args={.#<syntax:Users/mattei/Scheme-PLUS-for-Racket/main/Scheme-PLUS-for-Racket/src/bracket-apply.scm:126:30 list> {.#<syntax:72-interactions from an unsaved editor:17:40 +> .#<syntax:72-interactions from an unsaved editor:17:38 2> .#<syntax:72-interactions from an unsaved editor:17:42 x>}}
;; 3
  
(define-syntax $bracket-apply$ ;; this implements a possible bracket-apply as proposed in SRFI-105
  
  (lambda (stx)
    
    (syntax-case stx ()

      ;; a version that pre-compil the infix expression, should be faster
      (($bracket-apply$ container arg-bracket ...) ; . args-brackets

      
       (with-syntax ((parsed-args

		      (cons #'list 
		      	    (parse-square-brackets-arguments-lister-syntax (syntax->list #'(arg-bracket ...)))))) 
	 
	 ;;(newline)
	 ;;(display "bracket-apply : #'parsed-args=") (display #'parsed-args) (newline)
	 
	 #'($bracket-apply$next4list-args container parsed-args))))))

```

For this to be working i can imagine a solution with one of your Qi macro :

```scheme
(define-qi-syntax-rule ($bracket-apply$ container arg-bracket ...)
	    (esc (lambda (v)
	  	   (display "In $bracket-apply$ of define-qi-syntax-rule") (newline)
	  	   ($bracket-apply$ (v) container arg-bracket ...))))

```

this one seems to works but i can not test it (but tested with a true vector not a \_ wildcar, it worked ) because with this :

```scheme
(define Lplot {(src) ~> read-lines ~> list->vector ~> _[5 :] ~> vector->list ~> (△ {string-split ~> rest ~> (△ string->number) ~> vector}) ~> ▽})

```

wildcard \_ not allowed:

 ![Capture d’écran 2025-01-31 à 19.12.02](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/b/b4cca6b0de96b9facf885347a1459d37b3980100.png)

> [@countvajhula](#):
>
> If we try to use `&&` as an infix operator as `(bool {1 && 2})`, then I suspect this macro would issue (the famous) `bad syntax` error, because the `bool` macro gets control of expanding the expression, but it doesn't know what to do with `$nfx$`. And unlike Qi where we are able to get "inside" the language using macros, there's no way to recover from this in this `bool` macro.

yes ☹

```scheme
 (require syntax/parse/define)

(require syntax/parse/define)

#<eof>
> (define-syntax-parser bool
  [(_ ((~datum &&) a b)) #'(and a b)]
  [(_ ((~datum ||) a b)) #'(or a b)])

(define-syntax-parser
 bool
 ((_ ((~datum &&) a b)) #'(and a b))
 ((_ ((~datum \|\|) a b)) #'(or a b)))

#<eof>
> (bool (&& 1 2))

(bool (&& 1 2))
2

#<eof>
> (bool {1 && 2})

(bool ($nfx$ 1 && 2))
bool: expected one of these literal symbols: `&&' or `\|\|' in: $nfx$

```

but i suppose `define-syntax-parser` is special to Racket.

any idea to replace the \_ wildcard?

update:

with :

```scheme
(define-qi-foreign-syntaxes $bracket-apply$)

```

all is working now ,even this one:

```scheme
{Lplot := (src) ~> read-lines ~> list->vector ~> _[5 :] ~> vector->list ~> (△ {string-split ~> rest ~> (△ string->number) ~> vector}) ~> ▽}

```

🙂

 ![Capture d’écran 2025-01-31 à 19.30.06](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/0/0400d2c4b4352ee7c922e72a781995ffb5c559cb.png)

and the red dot spacecraft trajectory are non continous only because the original data are not good 🤣

update 2:

this one (with parenthesis) works too:

```scheme
{Lplot := (src) ~> read-lines ~> list->vector ~> _[5 :] ~> vector->list ~> (△ (string-split ~> rest ~> (△ string->number) ~> vector)) ~> ▽}

```

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [February 2, 2025, 1:24am UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/33 "2025-02-02T01:24:24Z")

</div>

That's great! 👍

> your mysterious macro

You may have already figured it out, but we are trying to rewrite

```scheme
($nfx$ f ~> g ~> ...)

```

occurring in a Qi context (i.e. the nested flow inside `△` in your example) to

```scheme
(esc (lambda (v) ($nfx$ (v) ~> f ~> g ~> ...)))

```

The initial `op` occurs _one extra time_ because we are introducing an arguments clause `(v)` that wasn't there in the original expression written by the user.

> ```scheme
> (bool ($nfx$ 1 && 2))
> bool: expected one of these literal symbols: `&&' or `\|\|' in: $nfx$
> 
> ```

Yeah, note that unlike `bool`, the ability to get cooperation from Qi by writing a Qi macro is a special feature provided by only a few macros in Racket (I can only think of Qi's `flow` (implemented using [Syntax Spec](https://github.com/michaelballantyne/syntax-spec) which provides this macro-extensibility) and Racket's [`match`](https://docs.racket-lang.org/reference/match.html#%28form._%28%28lib._racket%2Fmatch..rkt%29._match%29%29) which provides "match expanders").

So doing this infix → prefix tranformation in two stages feels risky in general. One idea is to avoid the `$nfx$` macro by doing the entire transformation from curly infix syntax to prefix syntax at the _read_ stage, as that would allow you to do all the transformations before any macros (including `bool`) get control of the syntax.

I don't have much experience with this (others here may have suggestions), but you may find [readtables](https://docs.racket-lang.org/guide/hash-reader.html#(part._readtable)) and [Beautiful Racket](https://beautifulracket.com/) useful, to explore this option and see if it's right for your use case.

> and the red dot spacecraft trajectory are non continous only because the original data are not good 🤣

Are you affiliated with [BepiColombo](https://www.esa.int/Science_Exploration/Space_Science/BepiColombo)? Seems very cool. I didn't realize Mercury had polar ice caps!

---

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [February 5, 2025, 3:53pm UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/34 "2025-02-05T15:53:12Z")

</div>

> [@countvajhula](#):
>
> Yeah, note that unlike `bool`, the ability to get cooperation from Qi by writing a Qi macro is a special feature provided by only a few macros in Racket (I can only think of Qi's `flow` (implemented using [Syntax Spec](https://github.com/michaelballantyne/syntax-spec) which provides this macro-extensibility) and Racket's [`match`](https://docs.racket-lang.org/reference/match.html#%28form._%28%28lib._racket%2Fmatch..rkt%29._match%29%29) which provides "match expanders").

I understand a bit,because probably it should be special Racket features that i do not know. Hope but not sure that all Qi feature could works for now in SRFI-105/curly infix because i do not know all in Qi.

> [@countvajhula](#):
>
> So doing this infix → prefix tranformation in two stages feels risky in general. One idea is to avoid the `$nfx$` macro by doing the entire transformation from curly infix syntax to prefix syntax at the _read_ stage, as that would allow you to do all the transformations before any macros (including `bool`) get control of the syntax.

I put it in my TODO list to have an option to in the parser to do fully the infix → prefix tranformation in one stage at the parser phase. This , of course , break compatibility with already implemented SRFI 105 curly infix implementations, such as the one of Guile for example, but anyway, my curly infix idea goes beyond what allow the basis of SRFI 105. So it is not a great problem, i should allow too some [pragmas](https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Pragmas.html) in the Scheme+ code that permit to swap dynamically from a strict SRFI 105 mode to an extended mode compatible with Qi macros and other language extensions. But this feature is not my first priority, and it it better to make it at the end when all the code of Scheme+ is done as i will have to duplicate or re-use a lot of routine in the first stage of parser. This is a long work.

> [@countvajhula](#):
>
> I don't have much experience with this (others here may have suggestions), but you may find [readtables](https://docs.racket-lang.org/guide/hash-reader.html#(part._readtable)) and [Beautiful Racket](https://beautifulracket.com/) useful, to explore this option and see if it's right for your use case.

**Beautiful Racket** was my starting point when porting SRFI 105 to Racket. The actual version allow the use of a `#lang reader SRFI-105` even if you can parse the code externally with `curly-infix2prefix4racket.rkt` which allow to have the exact line of eventual errors which can not be done (or i do not know?) with a reader. **Beautiful Racket** explained me step by step how to wrote a `reader`. (but again it uses Racket features not portable)

> [@countvajhula](#):
>
> and the red dot spacecraft trajectory are non continous only because the original data are not good 🤣

In fact the discontinuous was just an effect of scaling.

I asked the researcher and we checked the data i had because there was two different type of trajectories:

- FlyBy (red plot) when BepiColombo made a fly-by of the Mercury planet (grey sphere) but is currently orbiting around Sun (hope i'm not saying silly thing...)
- Insertion (blue plot), will be at the end of the year, when BepiColombo will be "injected" in the orbit around Mercury.

note: space travelling ( as far as it has been explained to me) require escape from earth but keeping the speed of earth to travel and use gravitational effect with other planets and sun (to accelerate or slow) and a bit reactor of spacecraft.

plotted with Racket/Qi/Scheme+/SRFI-105 code:

 ![Capture d’écran 2025-02-05 à 12.26.56](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/4/462869839e677009da075e2a1f92df7bc78bbe57.png)  
 ![Capture d’écran 2025-02-05 à 12.27.28](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/c/c36a8c7109410a93db54b4115e9818cb2b8d6685.png)

> [@countvajhula](#):
>
> Seems very cool. I didn't realize Mercury had polar ice caps!

yes ,probably ice shadowed in crater

> [@countvajhula](#):
>
> Are you affiliated with [BepiColombo](https://www.esa.int/Science_Exploration/Space_Science/BepiColombo)?

We are in [France at University of Nice](https://univ-cotedazur.fr/laboratoires/laboratoire-joseph-louis-lagrange-lagrange-1)

We find Racket amazing, the 3D axonometric plot is very usefull to quickly display and check data (even if a real 3D - not axonometric- view would be better)

To compare Qi and Scheme, here is 2 version of the data to plot generation:

Scheme/Racket/Scheme+:

```scheme
;; read all lines
{input-lines := (read-lines src)}
{vl := (list->vector input-lines)}

{tdl := vl[5 :]} ; TABLEDATA lines, skip the header to go to table data lines

(define Lplot (for/list ([tr tdl])
				    (list->vector (map string->number (rest (string-split tr))))))

```

and the Scheme/Qi/Scheme+ version:

```scheme
{Lplot := (src) ~> read-lines ~> list->vector ~> _[5 :] ~> vector->list ~> (△ (string-split ~> rest ~> (△ string->number) ~> vector)) ~> ▽}

```

Hope it is readable for every one, not only for Qi expert , this code make me think of an alien language 🙂 with strange characters `△``~>``▽` `-<` `><` like in this [sci-fi movie](https://youtu.be/9m7hPlL-v4A) . 😂

I think Qi is good but the documentation should provide greater examples, not just examples being a few tokens long. I would be interested to see what happens with long program, if it looks alien code or not 🙂 . Perheaps also it is better in infix , perheaps it is interesting to correlate Qi with SRFI-105/curly infix notation, i do not know. Anyway as far as i know the 2 syntaxes, Qi and Scheme+/SRFI 105 are still envolving.

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [February 5, 2025, 9:19pm UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/35 "2025-02-05T21:19:04Z")

</div>

> I put it in my TODO list to have an option to in the parser to do fully the infix → prefix tranformation in one stage at the parser phase. This , of course , break compatibility with already implemented SRFI 105 curly infix implementations, such as the one of Guile for example, but anyway, my curly infix idea goes beyond what allow the basis of SRFI 105. So it is not a great problem, i should allow too some pragmas in the Scheme+ code that permit to swap dynamically from a strict SRFI 105 mode to an extended mode compatible with Qi macros and other language extensions. But this feature is not my first priority, and it it better to make it at the end when all the code of Scheme+ is done as i will have to duplicate or re-use a lot of routine in the first stage of parser. This is a long work.

Sounds like a good plan.

> plotted with Racket/Qi/Scheme+/SRFI-105 code:

I hope you don't mind, I've included this in the Qi Wiki, in [a section dedicated to cool and fun things](https://github.com/drym-org/qi/wiki/Qi-in-the-Wild#so-near-yet-so-far-by-damien-mattei) done by users.

> We find Racket amazing, the 3D axonometric plot is very usefull to quickly display and check data (even if a real 3D - not axonometric- view would be better)

That's great!

> Hope it is readable for every one, not only for Qi expert , this code make me think of an alien language 🙂 with strange characters △ ~\> ▽ -\< \>\< like in this sci-fi movie . 😂

As long as your computer doesn't blow up when you run the code 😄

> I think Qi is good but the documentation should provide greater examples, not just examples being a few tokens long. I would be interested to see what happens with long program, if it looks alien code or not 🙂 . Perheaps also it is better in infix , perheaps it is interesting to correlate Qi with SRFI-105/curly infix notation, i do not know. Anyway as far as i know the 2 syntaxes, Qi and Scheme+/SRFI 105 are still envolving.

There are some [longer programs here](https://docs.racket-lang.org/qi/When_Should_I_Use_Qi_.html), and yes, it will be fun to see what other syntactic variations emerge.

---

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [February 6, 2025, 10:54pm UTC](https://racket.discourse.group/t/apply-values-to-a-procedure/3506/36 "2025-02-06T22:54:34Z")

</div>

> [@countvajhula](#):
>
> I hope you don't mind, I've included this in the Qi Wiki, in [a section dedicated to cool and fun things](https://github.com/drym-org/qi/wiki/Qi-in-the-Wild#so-near-yet-so-far-by-damien-mattei) done by users.

it is well. thank you 👍

> [@countvajhula](#):
>
> As long as your computer doesn't blow up when you run the code 😄

😂

[Previous page](https://racket.discourse.group/t/apply-values-to-a-procedure/3506.md?page=1)
