Is there anything in Racket like the pipe forward operator (|>) that I've seen in Haskell, F# and Elixir?
For those unfamiliar with this operator it simply passes the output of one function as the input to the next. So this:
(f (g x))
Would become this:
(f x) |> g
Or something like that. I tried creating it myself but no doubt | is reserved for other purposes in Racket. And I'd really like to have it because it can simplify nested calls quite a bit! I'm sure others have already built something like this but I'm not sure what to google for hence I ask here.
And btw yes, | is reserved -- it's used to read some characters literally, without any special meaning those characters might otherwise have while reading the input. Racket is an S-expression / symex-oriented language, meaning that almost everything has the syntax (f x ...), where f is either a function or a macro. So although you could implement a rule like what you had there:
(f x) |> g --> (f (g x))
... it would need to be done as a reader extension (relatively rare) and not as a simple macro (very common and easy). Since S-expressions are such a versatile and explicit syntax, it's easy to write extensions to the language as rules transforming one S-expression to another and these are what we call macros. Qi is one such implementation of this behavior as a macro. The threading macro is another.
As previously answered it needs a reader extension or external parser and use a library (treading macro or Qi)
You can use as reader extension SRFI 105 curly infix, i have implemented one for Racket, but for now ( see note below) it is simpler to use Scheme+ for Racket
here is the running example:
Welcome to DrRacket, version 8.14 [cs].
Language: reader SRFI-105, with debugging; memory limit: 8192 MB.
SRFI-105 Curly Infix parser for Racket Scheme and R6RS by Damien MATTEI
(based on code from David A. Wheeler and Alan Manuel K. Gloria.)
(require threading)
{1 ~> add1 ~> sub1}
1
{2 + {1 ~> add1 ~> sub1}}
3
'{(f x) ~> g}
'(~> (f x) g)
{3 ~> sqr ~> add1}
10
{3 ~> sub1 ~> sqr ~> add1}
5
note: normally only SRFI 105 is enought to have some infix notation if you enabled :
(define srfi-strict #t) ; enable strict compatibility with SRFI 105
in the source code. (for now it is set to #f)
Note also that in an infix expression the new operator ~> should have a defined an operator precedence rule.
Then the same syntax with ( ) instead of { } could be used.
All that are interesting ideas , i will put them in the next release of Scheme+.
Just beware that some Qi flows may not combine well with TR—there's not a "typed Qi" and macros are especially prone to TR issues. See https://github.com/drym-org/qi/issues/18
(As much as I love Qi, the threading package doesn't suffer as much from this problem because it performs a direct textual rewrite. Qi is structured more as a compiler of a complex DSL, so you can split the specification (flow (~> times-ten turn-to-string)) from the application (… n); this means it produces output that is harder for TR to reason about.)
Yeah that's why I worked up that example; was wondering if Qi could work with TR. I guess I just happened to find a case that didn't cause that issue! Thanks for making me aware of that little potential landmine.
To add to what Ben said, it would be wonderful to support typed behavior with Qi, whether that's finding ways to interoperate better with Typed Racket, or developing a typed variant of Qi (which may also play well with TR). There have been a few community members who have expressed interest in this, so maybe with enough data and ideas, it would be feasible to make meaningful progress here. For the moment, if you continue to experiment along these lines, it would be valuable if you could share any experiences or desires (e.g., by reporting them on the Typed Qi issue linked above, or as a new issue).
I'm happy to experiment! I don't believe I know enough about TR, Qi or Racket in general to contribute fixes for problems (yet) but I suppose trying things out and reporting issues I find is also helpful right?