I was bemused to realise that I've actually been programming for literally 50 years. It finally seeped through my thick skull I make enough mistakes that if it's hard to read, I probably got it wrong. And THIS code fragment is hard to read. I don't care if you use parentheses or pipes, it's hard to read either way. Oh, the pipes make the structure easier to see, true. But I am still left guessing what it is FOR. What's it SUPPOSED to mean? And the problem is that there are some abstractions missing. Of course this is JSON's fault.
This is the first code smell, and in my experience it is almost ALWAYS a code smell: you are using JSON as a "processing" data structure instead of as a "communication" syntax. Using JSON inside your program, instead of at the edges, means that the semantics gets scattered all over the code, which leads to complexity and inconsistency. The convention I follow is that data structure more complicated than a string or an array of numbers has a Smalltalk class Whatsit>>asJson converts an instance to a JSON value Whatsit class>>fromJson: converts a JSON value to an instance. I'll start with topLevel := TopLevelWhatsit fromJson: someStream nextJson. and from then on I'm working with pure Smalltalk. This has the extra benefit of validating the input right away. I don't want my program running for several hours and then running into trouble because some component of the JSON value is missing or ill-formed. In practice, the time cost of converting JSON to (application- specific) Smalltalk is quite small compared with the cost of reading the JSON in the first place, and there can be seriously worthwhile savings in memory. For this example, we'd be looking at topLevel tree blobs collect: [:each | each path] thenSelect: [:path | path hasAnyExtension: #('md' 'mic')] My Filename class has methods has[Any]Extension:[ignoringCase:] which I have shamelessly exploited here. I like the way that they hide the structure of a Filename. The portmanteau methods Collection>>collect:thenSelect: Collection>>select:thenCollect: have existed in Pharo as long as Pharo has existed. They have two rationales: (a) improve readability (b) permit optimisation by eliminating an intermediate collection. Sequences exploit (b). Sets could too but happen not to. THEREFORE, here are free implementations of Set>>collect:thenSelect: and Set>>select:thenCollect: consistent with Pharo's Set>>collect: collect: collectBlock thenSelect: selectBlock "Override Collection>>collect:thenSelect: like OrderedCollection. Beware: 'self species' is often inappropriate, as in #collect:." |newSet| newSet := self species new: self size. self do: [:each | |item| item := collectBlock value: each. (selectBlock value: each) ifTrue: [newSet add: item]]. ^newSet select: selectBlock thenCollect: collectBlock "Override Collection>>select:thenCollect: like OrderedCollection. Beware: 'self species' is often inappropriate, as in #collect:." |newSet| newSet := self species new: self size. self do: [:each | (selectBlock value: each) ifTrue: [ newSet add: (collectBlock value: each)]]. ^newSet On Wed, 26 Jan 2022 at 22:19, Kasper Osterbye <kasper.oster...@gmail.com> wrote: > Cheers all > > I have noticed that I often ends up with quite a number of nested > expressions, for example: > > (((json at: 'tree') > select: [ :e | (e at: 'type') = ‘blob' ]) > collect: [:e | Path from: (e at: 'path')]) > select: [ :p | p segments last > in: [ :name | (name endsWith: '.md') | > (name endsWith: '.mic') ] ] > > What kind of proposals (if any) have been for a different syntax which > could give a more streamlined syntax? > > My own thinking has been around an alternative to the cascade semicolon. > What symbol to use does not matter for me, but something like > json at: ‘tree' º > select: [ :e | ((e at: 'type') = 'blob’)]º > collect: [:e | Path from: (e at: 'path’)]º > select: [ :p | p segments last > in: [ :name | (name endsWith: '.md') | (name endsWith: > '.mic') ] ] > > Basically, a send the right hand expression to the result of the left hand > expression. > > Has anyone ever tried this, or is it just one of the many small annoyances > best left alone? > > Best, > > Kasper