Hi, Racket Discourse.
I have some free time this morning, so I thought I'd ask your opinion on using the "infix" form of application, namely (f x y) -> (x . f . y)
, and maybe waste your time enjoyably.
Personally, I am a big fan. I don't use it everywhere, but it is nigh unbeatable when one needs to make clearer the composition of certain dense expressions.
Now, just this morning I was browsing the r/Racket
subreddit and I saw someone mentioning that it's "probably not idiomatic, but it is cool" (I paraphrase).
Is this a common sentiment? It is a part of the language; I would argue that it is precisely idiomatic in the sense that it forms a particular idiom which is, if not "unique" to Racket, at least not very common in other languages (of which I know). I also don't see that it makes code less clear or readable.
Tangent:
I often think of lojban
(a constructed language, of which I am not a speaker or reader) when using this form of expression. The language has this concept of verb-relationships, which could be likened to the application of a macro or procedure, the head (applicative?) being the relationship in this case, and its arguments being the noun-components (perhaps, if one wanted to stretch the metaphor, keywords might be like adverbs or prepositions, or whatever).
Furthermore, it allows you to specify the relative ordering of the noun-components using something like prepositions to indicate the positionality, so in "Racket-y" terms:
(rel #:2nd noun #:1st noun)
and so on.
And, as with Racket, the verb-relationship can go almost anywhere in the sentence, so:
(#:1st noun . rel . #:2nd noun)
makes sense in this context.
This maps more or less clearly to procedures, but with macros this is not exactly (ahem) applicable, because the syntax of the macro is more positionally dependent, and cannot necessarily be mangled in this way.
In a recent adventurous attempt to mess around with alternative conditionals
, I became newly interested in using verbs and nouns to describe code.
In a somewhat related post, @lexi.lambda made a very interesting point I would probably not have been able to articulate myself:
One can group macros into two categories (not absolutely, of course, but for the sake of argument), namely, those which abbreviate intent, and those which abstract intent.
The difference being that an "abbreviation" is context-free (plus-minus) and "exactly equivalent" to the more verbose form of the expression; while "abstraction" is more like a black-box in the sense that it takes some inputs, and based on what it has been defined to do and possibly using unseen information, will then produce the intended result, although the original structure may or may not be recoverable or even recognizable from the end product.
Where am I going with this? Well, as an example, I don't like putting my handlers
at the top of my code when dealing with possible exceptions. So much so, that I have recently taken to using this custom form:
(define-syntax-rule
(body ...
. with-exceptions .
([exn handler] ...))
#;becomes
(with-handlers ([exn handler] ...)
body ...))
So that I may write this, instead:
((let loop ([deadline #false])
(sync
(if deadline
(handle-evt deadline (thunk* (loop #false)))
(handle-evt
checkup
(lambda (_ timestamp)
(log-application-info "alive, next check in 10 minutes")
; create an alarm for 1 second after the timestamp
(define deadline (alarm-evt (+ (* timestamp 1000) 1000)))
(loop deadline))))))
. with-exceptions . ; HERE I AM
([exn:break?
(lambda _
(log-schedule-info "stopping")
(shutdown-scheduler)
(log-application-info "stopping")
(shutdown-log-receivers))]))
I am wondering, if it would not be useful (or maybe someone has even already done this), to be able to specify in a more general manner where what is supposed to go, and in what order.
Obviously, the syntax-rule
is doing that in this instance, but it seems wasteful? that I have to write a "new form" to achieve this flexibility, which someone else has to go and inspect to remove the "black-box-ness" and discover what it does (which is normal, but frowned upon--not everyone feels the way I do about the way things should be presented).
I cannot just use (x . with-handlers . y)
because the position of the handlers remains the same, so I have to resort to the syntax-adjustment.
What if there were a related mechanism to (x . f . y)
which allowed one to specify that a particular expression is supposed to be the n-th
thing in a particular form, without necessarily having to modify or wrap the original in extra machinery. Almost like a keyword, but perhaps not because this might be confusing.
In the example of with-handlers
then, maybe one might write:
(#:2nd body . with-handlers . #:1st handlers)
instead of having to define manually a new macro (abbreviation) which simply rearranges the resulting code.
What do you think; have you come across something like this before, and would you think it to be a "bad idea" if someone proposed it?
P.S.
All my ideas are half-baked; so, it could be cake, or it could be fake. You decide.