LiveScript icon indicating copy to clipboard operation
LiveScript copied to clipboard

Reintroduce +++ operator to mean concatenation with mutation

Open determin1st opened this issue 3 years ago • 16 comments

Can you tell why deprecate +++ operator? It doesn't mess with ++ right, must be the same precendence with ++, so could be "recovered" easily? Any story about it maybe :]

my "projected" use-case:

# inside of object constructor function...
# ...
	@item = item = {} # all
	@list = list = [root] # all ordered
	####
	list +++ (querySelectorChildren box, '.item')
	a = -1
	while ++a < list.length
		if b = querySelectorChild list[a], '.section'
			list +++ (querySelectorChildren b, '.item')
# ...
# end of example

determin1st avatar Sep 05 '20 17:09 determin1st

It's just been renamed to  ++  (note the spaces; unspaced ++ is increment). Your example works if you replace all the +++ with ++= (you need the = because  ++  doesn't mutate the lists, it only returns their concatenation).

rhendric avatar Sep 05 '20 17:09 rhendric

ye, i figured only ++ won't go, so thanks, didn't know about ++=, will check

determin1st avatar Sep 05 '20 17:09 determin1st

one more thing about it (generated from ++=):

      while (++a < list.length) {
        if (b = querySelectorChild(list[a], '.section')) {
          list = list.concat(querySelectorChildren(b, '.item'));
        }

the assignment is not needed, right, should be only list.concat(..)

determin1st avatar Sep 05 '20 17:09 determin1st

oh, my, i've missed the bug then..

any chance to resurrect +++ from the imperative hell?

determin1st avatar Sep 06 '20 13:09 determin1st

+++ did exactly the same as ++ does

vendethiel avatar Sep 06 '20 13:09 vendethiel

maybe let's tweak it to Array.splice ? so it will mutate the left operand? i mean new +++ with .splice

determin1st avatar Sep 06 '20 15:09 determin1st

Why? just use ++=

vendethiel avatar Sep 06 '20 16:09 vendethiel

because +++ is a sister of <<<

with ++= i have to follow this path:

# ...
	item = {} # all
	list = [root] # all ordered
	####
	list ++= (querySelectorChildren box, '.item')
	a = -1
	while ++a < list.length
		if b = querySelectorChild list[a], '.section'
			list ++= (querySelectorChildren b, '.item')
	# assign one more time :(
	@item = item
	@list = list
# ...

see, i could assign it one-line at the top, have to add 2 more lines. with the .splice as +++ it would be

# ...
	@item = item = {} # all
	@list = list = [root] # all ordered
	####
	list +++ (querySelectorChildren box, '.item')
	a = -1
	while ++a < list.length
		if b = querySelectorChild list[a], '.section'
			list +++ (querySelectorChildren b, '.item')
# ...

makes sense?

determin1st avatar Sep 06 '20 20:09 determin1st

@determin1st Why can't you use @list and @item during the operations?

# ...
	@item = {} # all
	@list = [root] # all ordered
	####
	@list ++= (querySelectorChildren box, '.item')
	a = -1
	while ++a < @list.length
		if b = querySelectorChild @list[a], '.section'
			@list ++= (querySelectorChildren b, '.item')
# ...

What is wrong with above code?

ceremcem avatar Sep 06 '20 22:09 ceremcem

IMO, if you want to mutate an array by appending new elements, you should just call .push on it. This is subjective, but based on experience with similarly-spelled operators I wouldn't expect an expression spelled a +++ b to mutate a, or even treat a and b fundamentally differently.¹ a <<< b is at least visually asymmetric enough to hint at the side effect. I know LiveScript has a whole mess of operators, but I don't think more operators need to be introduced just as aliases to methods. a.push ...b is much clearer about what's going on, is already familiar to every JavaScript programmer, and is, what, 9 characters instead of 5? Not exactly a huge downside. It doesn't look as mathematical, but since what's happening isn't a mathematical concatenation but rather an impure mutation, I think that's a positive.

  1. In Haskell, which is the only language I know with a +++ operator in the core library, +++ is a way to combine functions²; f +++ g is a function that can take a value tagged Left and apply f to it, or a value tagged Right and apply g to it. Haskell's ++ operator means the same thing as in LiveScript.
  2. Well, arrows, but anyone who needs this explanation probably doesn't need to worry about the difference.

rhendric avatar Sep 07 '20 22:09 rhendric

@ceremcem well ye, i only wanted a bit of perfectionism, that can be done in multiple ways, but somehow +++ appeared as a natural thing when i wrote the initializer's code.

@rhendric 9 characters plus engine implementation dependent, can't say how much arguments allowed to push(...b), i mean just a loop would be more solid and maybe faster

determin1st avatar Sep 08 '20 17:09 determin1st

Which implementations don't support push with multiple arguments? It's in the ES3 spec, which is the version of JS that LiveScript nominally targets as a baseline when not using features that more or less explicitly require more modern engines, like generators and promises.

rhendric avatar Sep 08 '20 17:09 rhendric

i mean here, the "Merging two arrays" section: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

says:

Do not use this method if the second array (moreVegs in the example) is very large because the maximum number of parameters that one function can take is limited in practice. See apply() for more details.

i checked the limit was 65535 for the second array in Chromium. Sure, it's hard to reach but still..

determin1st avatar Sep 09 '20 08:09 determin1st

.splice is presumably subject to the same limitation, right? So if this matters to you, the only viable approach would be to use (either manually, or have some syntax compile into) a loop. But I'm guessing that for such large arrays, .concat would be faster than a loop, so the best thing for large arrays would be ++= and the best thing for small arrays would be .push .... Since PureScript can't know how big your arrays are, the programmer has to select the best approach. So I think you would need to make the case that whatever +++ would compile to is better than .push ... for small arrays, or better than ++= for large arrays. What do you think about that?

rhendric avatar Sep 09 '20 15:09 rhendric

i thought that .splice takes array as an argument first, it doesn't, so it doesn't fit.

i've made some tests: http://jsbench.github.io/#482b62ecdddfeffcea89d30ded47adb6

so, by the number of elements (in the second array):

20: loop is 18% faster 200: push is 38% faster 2000: push is 36% faster 20000: push is 50% faster 200000: push is dead, maximum call stack exceeded

.push is becoming faster starting from 60 elements in the second array .concat is becoming faster starting from 50 elements in the second array

so, for small arrays <60 elements and also for super huge arrays the loop is better

i doubt that speed should be the driving factor of +++, the main point (feature) is the mutation, right

determin1st avatar Sep 10 '20 10:09 determin1st