Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

pipes.fz


# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation.  If not, see <https://www.gnu.org/licenses/>.


# -----------------------------------------------------------------------
#
#  Tokiwa Software GmbH, Germany
#
#  Source code of Fuzion standard library infix pipe features
#
#  Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------


# infix |> -- pipe with one argument
#
# This allows changing the order of function application: instead of
#
#   l := sum ([1,2,3,4].map **2)
#
# you can write
#
#   l := [1,2,3,4].map **2 |> sum
#
# which often correponds more naturally to the data flow through the code.
#
public infix |> (A, R type, a A, f A->R) =>
  f a


# infix ||> -- pipe with a two-tuple argument, destructuring the tuple into arguments
#
# This allows changing the order of function application: instead of
#
#   f(a,b i32) => a+b
#   l1 := [1,2,3,4]
#   l2 := [4,3,2,1}
#   l := l1.pairs l2
#          .map p->{(p1,p2) := p; f p1 p2}
#
# you can write
#
#   l1 := [1,2,3,4]
#   l2 := [4,3,2,1}
#   l := l1.pairs l2
#          .map (p -> p ||> f)
#
# which often correponds more naturally to the data flow through the code.
#
public infix ||> (A, B, R type, a (A,B), f (A,B)->R) =>
  f a.values.0 a.values.1


# infix |||> -- pipe with a three-tuple argument, destructuring the tuple into arguments
#
# This allows changing the order of function application: instead of
#
#   f(a,b,c i32) => a+b+c
#   t := (1,2,3)
#   r := f t.0 t.1 t.2
#
# you can write
#
#   f(a,b,c i32) => a+b+c
#   t := (1,2,3)
#   r := t |||> f
#
# which often correponds more naturally to the data flow through the code.
#
public infix |||> (A, B, C, R type, a (A,B,C), f (A,B,C)->R) =>
  f a.values.0 a.values.1 a.values.2


# infix ||||> -- pipe with a four-tuple argument, destructuring the tuple into arguments
#
# This allows changing the order of function application: instead of
#
#   f(a,b,c,d i32) => a+b+c+d
#   t := (1,2,3,4)
#   r := f t.0 t.1 t.2 t.3
#
# you can write
#
#   f(a,b,c,d i32) => a+b+c+d
#   t := (1,2,3,4)
#   r := t ||||> f
#
# which often correponds more naturally to the data flow through the code.
#
public infix ||||> (A, B, C, D, R type, a (A,B,C,D), f (A,B,C,D)->R) =>
  f a.values.0 a.values.1 a.values.2 a.values.3


# infix |||||> -- pipe with a five-tuple argument, destructuring the tuple into arguments
#
# This allows changing the order of function application: instead of
#
#   f(a,b,c,d,e i32) => a+b+c+d+e
#   t := (1,2,3,4,5)
#   r := f t.0 t.1 t.2 t.3 t.4
#
# you can write
#
#   f(a,b,c,d,e i32) => a+b+c+d+e
#   t := (1,2,3,4,5)
#   r := t |||||> f
#
# which often correponds more naturally to the data flow through the code.
#
public infix |||||> (A, B, C, D, E, R type, a (A,B,C,D,E), f (A,B,C,D,E)->R) =>
  f a.values.0 a.values.1 a.values.2 a.values.3 a.values.4


# infix ||||||> -- pipe with a six-tuple argument, destructuring the tuple into arguments
#
# This allows changing the order of function application: instead of
#
#   f(a,b,c,d,e,f i32) => a+b+c+d+e+f
#   t := (1,2,3,4,5,6)
#   r := f t.0 t.1 t.2 t.3 t.4 t.5
#
# you can write
#
#   f(a,b,c,d,e,f i32) => a+b+c+d+e+f
#   t := (1,2,3,4,5,6)
#   r := t ||||||> f
#
# which often correponds more naturally to the data flow through the code.
#
public infix ||||||> (A, B, C, D, E, F, R type, a (A,B,C,D,E,F), f (A,B,C,D,E,F)->R) =>
  f a.values.0 a.values.1 a.values.2 a.values.3 a.values.4 a.values.5


# a six-tuple is large enough for two 3-D coordinates, so let's stop here for now....


# infix <| -- backwards pipe with one argument
#
# This operation is seldom useful, it is provided only for reasons of symmetry with |>.
# Instead of
#
#   l := [1,2,3,4].map **2 |> sum
#
# you can also write
#
#   l := sum <| [1,2,3,4].map **2
#
# which often correponds more naturally to the data flow through the code.
#
public infix <| (A, R type, f A->R, a A) =>
  f a


# infix <|| -- backwards pipe with a two-tuple argument, destructuring the tuple into arguments
#
# This allows destructuring of tuples as actual arguments: instead of
#
#   f(a,b i32) => a+b
#   l1 := [1,2,3,4]
#   l2 := [4,3,2,1}
#   l := l1.pairs l2
#          .map p->{(p1,p2) := p; f p1 p2}
#
# you can write
#
#   l1 := [1,2,3,4]
#   l2 := [4,3,2,1}
#   l := l1.pairs l2
#          .map (p -> f <|| p)
#
# .
#
public infix <|| (A, B, R type, f (A,B)->R, a (A,B)) =>
  a ||> f


# infix <||| -- backwards pipe with a three-tuple argument, destructuring the tuple into arguments
#
# This allows destructuring of 3-tuples as actual arguments: instead of
#
#   f(a,b,c i32) => a+b+c
#   t := (1,2,3)
#   r := f t.0 t.1 t.2
#
# you can write
#
#   f(a,b,c i32) => a+b+c
#   t := (1,2,3)
#   r := f <||| t
#
# which often correponds more naturally to the data flow through the code.
#
public infix <||| (A, B, C, R type, f (A,B,C)->R, a (A,B,C)) =>
  a |||> f


# infix <|||| -- backwards pipe with a four-tuple argument, destructuring the tuple into arguments
#
# This allows destructuring of 4-tuples as actual arguments: instead of
#
#   f(a,b,c,d i32) => a+b+c+d
#   t := (1,2,3,4)
#   r := f t.0 t.1 t.2 t.3
#
# you can write
#
#   f(a,b,c,d i32) => a+b+c+d
#   t := (1,2,3,4)
#   r := f <|||| t
#
# which often correponds more naturally to the data flow through the code.
#
public infix <|||| (A, B, C, D, R type, f (A,B,C,D)->R, a (A,B,C,D)) =>
  a ||||> f


# infix <||||| -- backwards pipe with a five-tuple argument, destructuring the tuple into arguments
#
# This allows destructuring of 5-tuples as actual arguments: instead of
#
#   f(a,b,c,d,e i32) => a+b+c+d+e
#   t := (1,2,3,4,5)
#   r := f t.0 t.1 t.2 t.3 t.4
#
# you can write
#
#   f(a,b,c,d,e i32) => a+b+c+d+e
#   t := (1,2,3,4,5)
#   r := f <||||| t
#
# which often correponds more naturally to the data flow through the code.
#
public infix <||||| (A, B, C, D, E, R type, f (A,B,C,D,E)->R, a (A,B,C,D,E)) =>
  a |||||> f


# infix <|||||| -- backwards pipe with a six-tuple argument, destructuring the tuple into arguments
#
# This allows destructuring of 6-tuples as actual arguments: instead of
#
#   f(a,b,c,d,e,f i32) => a+b+c+d+e+f
#   t := (1,2,3,4,5,6)
#   r := f t.0 t.1 t.2 t.3 t.4 t.5
#
# you can write
#
#   f(a,b,c,d,e,f i32) => a+b+c+d+e+f
#   t := (1,2,3,4,5,6)
#   r := f <|||||| t
#
# which often correponds more naturally to the data flow through the code.
#
public infix <|||||| (A, B, C, D, E, F, R type, f (A,B,C,D,E,F)->R, a (A,B,C,D,E,F)) =>
  a ||||||> f


# a six-tuple is large enough for two 3-D coordinates, so let's stop here for now....