functionapldyalog

Two APL functions give different results, but their boxing is identical


I am trying to create an APL function which returns differences (non-identical items with identical index) between two vectors. I have come up with the following and it works fine, subtracting two vectors and discarding zeroes from the result:

func ← {((⍺-⍵)≠0)/(⍺-⍵)}

However, I was not satisfied with repeating the (⍺-⍵) part, so I optimized it a little:

func ← {(⍺ (0≠-) ⍵) / (⍺-⍵)}

That also works ((1 2 3 4) func (4 2 0 4) returns -3 3, as expected), so I went ahead:

func ← {⍺ ((0≠-)/-) ⍵}

And that, in fact, does not work for vectors longer than one element. It just returns 1 whenever there is a difference, without showing how big it is ((1 2 3 4) func (4 2 0 4) now returns 1). Why?

I checked the problematic function both in https://tryapl.org editor and in a local environment - neither works.
I checked the composition rules again - I tried to use the one saying that ⍺ (f g h) ⍵ and (⍺ f ⍵) g (⍺ h ⍵) are equivalent, where in my case:

Perhaps the most peculiar thing for me - I checked the boxing of two functions. It's identical!

⍝ the working function
⍝ func ← {(⍺ (0≠-) ⍵) / (⍺-⍵)}

    ]boxing on
    ((0≠-))/(-)
┌───────────┬─┐
│┌───────┬─┐│-│
││┌─┬─┬─┐│/││ │
│││0│≠│-││ ││ │
││└─┴─┴─┘│ ││ │
│└───────┴─┘│ │
└───────────┴─┘
⍝ the "broken" function
⍝ func ← {⍺ ((0≠-)/-) ⍵}

    ]boxing on
    ((0≠-)/-)
┌───────────┬─┐
│┌───────┬─┐│-│
││┌─┬─┬─┐│/││ │
│││0│≠│-││ ││ │
││└─┴─┴─┘│ ││ │
│└───────┴─┘│ │
└───────────┴─┘

It's also identical in tree mode and parentheses mode.

What happened? Am I not allowed to nest trains? Did I get my composition parameters wrong? Did I make a typo while checking the boxings?


Solution

  • I think your problem is that / wants to be an operator in a train. You have to coerce it into its function form:

      1 2 3 4 ((0≠-)⊢⍤/-) 4 2 0 4
    ┌→───┐
    │¯3 3│
    └~───┘
    

    The ⊢⍤/ might be weird-looking, but it's the "slash-as-function" pattern to commit to memory when using trains.

    Note the difference:

      (0≠-)/-
        ┌┴┐
        / -
      ┌─┘
    ┌─┼─┐
    0 ≠ -
    
      (0≠-)⊢⍤/-
      ┌────┼─┐
    ┌─┼─┐  ⍤ -
    0 ≠ - ┌┴┐
          ⊢ /