Functions: Difference between revisions

From Adam Colton
Jump to navigation Jump to search
No edit summary
No edit summary
Line 18: Line 18:
Assuming Gryphon allows only a single return, then the most common case would be (like Rust) a tagged union with errors. If the errors are specific, we can create a list of all the possible errors.
Assuming Gryphon allows only a single return, then the most common case would be (like Rust) a tagged union with errors. If the errors are specific, we can create a list of all the possible errors.


== Closures ==
== Curry Closures ==
I'm considering not allowing closures. The same thing can be accomplished with anonymous structs:
I think closures are a bad idea - they are a good source of errors and complicate what data a function has access to.
  func curryAdd(a int) func(b int) int{
    return func(b int) int{
      return a+b
    }
  }
 
  // explicit
  type curryAddStruct struct{
    a int
  }
  func (cas curryAddStruct) add(b int) int{
    return cas.a + b
  }
  func curryAdd(a int) func(b int) int{
    return curryAddStruct{a}.add
  }
 
  // anonymous
  func curryAdd(a int) func(b int) int{
    return func(cas {a:a} struct{a int}) _(b int) int{
      return cas.a+b
    }
  }
 
  // very anonymous
  func curryAdd(a int) func(b int) int{
    return func(a) _(b int) int{
      return a+b
    }
  }


So the receiver on a method can accept anonymous context.
Instead I want to use currying.
 
  const Add = (a, b int)-->(int){return a+b}
  c5 = Add::(5) // c5 is now type (int)-->(int)


== Inline ==
== Inline ==
Line 58: Line 31:
Of course, a function only called from one place should always be inlined.
Of course, a function only called from one place should always be inlined.


== Context Struct and Methods ==
A function really takes an anonymous struct as context and may attach a method to the namespace of the first argument as a method:
  func (f Foo) Bar(a,b int)
is like
  method Bar{f Foo; a,b int}
and returns just add more context
  func (f Foo) Bar(a,b int) (c int)
is
  method Bar{ctxIn {f Foo; a,b int}; ctxOut{c int}}
[[Category:Gryphon]]
[[Category:Gryphon]]

Revision as of 14:21, 2 October 2019

Basics

A function takes some argument and may return a value (or multiple values).

Multiple Returns

Not sure about these, there's an elegance to only allowing a single return type. With the tagged unions, it's not necessary the way it is with go.

Implicit Attributes

Pure

A pure function has no side effects. A pure function invoked with static arguments can be statically replaced at compile time.

Unsafe libraries can override this. The use cases are logging and memoization.

Async

If a function can cause a wait operation it is async. This is implicit to avoid the "what color" problem.

Error Types

Assuming Gryphon allows only a single return, then the most common case would be (like Rust) a tagged union with errors. If the errors are specific, we can create a list of all the possible errors.

Curry Closures

I think closures are a bad idea - they are a good source of errors and complicate what data a function has access to.

Instead I want to use currying.

 const Add = (a, b int)-->(int){return a+b}
 c5 = Add::(5) // c5 is now type (int)-->(int)

Inline

The compiler should be able to make an informed decision about inlining function calls. We may want a compiler flag to help tweak the threshold (setting the desired balance between performance and size).

Of course, a function only called from one place should always be inlined.

Context Struct and Methods

A function really takes an anonymous struct as context and may attach a method to the namespace of the first argument as a method:

 func (f Foo) Bar(a,b int)

is like

 method Bar{f Foo; a,b int}

and returns just add more context

 func (f Foo) Bar(a,b int) (c int)

is

 method Bar{ctxIn {f Foo; a,b int}; ctxOut{c int}}