I have a swift implementation of the haskell <*> operator that seems to work as long as the arguments are arrays:
public func <*> <T, U>(left:[(T)->U], right:[T]) -> [U] {
return flatten(map(left) { (function) -> [U] in
return map(right) { return function($0) }
})
}
I'm trying to make it more general by rewriting it to use sequences instead of arrays, but I'm having difficulty with the syntax to require that a sequence be a sequence of functions. This works to generalize the right argument, but not the left:
public func <*> <T, U, Tseq:SequenceType where Tseq.Generator.Element == T>(left:[(T)->U], right:Tseq) -> [U] {
return flatten(map(left) { (function) -> [U] in
return map(right) { return function($0) }
})
}
Now I'm trying to generalize the left part, but running into syntax errors. It seems like it ought to be:
public func <*> <
T,
U,
Tseq:SequenceType where Tseq.Generator.Element == T,
Fseq:SequenceType where Fseq.Generator.Element == (T) -> U
>(left:[(T)->U], right:Tseq) -> [U] {
return flatten(map(left) { (function) -> [U] in
return map(right) { return function($0) }
})
}
But that gives me an error on the Fseq... line:
Expected '>' to complete generic parameter list
What is the proper syntax (or is there no proper syntax) to require that Fseq.Generator.Element be a function taking a T and returning a U?
Couple of problems (one fixable, one more fatal):
You have the syntax for the generic template a bit off. There’s only one where clause for all the placeholders, rather than an optional one per placeholder. So it would be more like:
public func <*> <
T, U, Tseq: SequenceType, Fseq: SequenceType
where Fseq.enerator.Element == T -> U,
Tseq.Generator.Element == T>
(left:[(T)->U], right:Tseq) -> [U] {
return flatten(map(left) { (function) -> [U] in
return map(right) { return function($0) }
})
}
However, that still won’t work because you can’t have expressions more complex than single types on the rhs of a == (not even tuples of two placeholders). So where Fseq.Generator.Element == T->U is not going to fly.
You might want to look at how swiftz does this – looks like it requires an additional struct.
Related
I would like for a higher order function to be able to catch the signature parameters of the passed function which can have different signature.
I don't know if it's feasible but this was my approach to it :
type FuncA = (a: string, b: number) => void
type FuncB = (a: string) => void
type Func = FuncA | FuncB
const a: FuncA = (a: string, b: number) => {
console.log('FuncA')
}
const b: FuncB = (a: string) => {
console.log('FuncB')
}
// My higher order function
const c = (func: Func) => {
// do something here...
return (...args: Parameters<typeof func>) => {
func(...args) // Expected 2 arguments, but got 0 or more. ts(2556). An argument for 'a' was not provided.
}
}
My higher order function c couldn't pass the parameters of func
It seems like TypeScript cannot discriminate the different possible signature of type Func.
Does anyone know a pattern to write this kind of code?
Thank you !
This is a tough one because for a function to extend another function doesn't mean quite what you think.
We want the function created by c to require that arguments correspond to the function that it was given. So we use a generic to describe the function.
const c = <F extends Func>(func: F) => {
return (...args: Parameters<F>) => {
func(...args); // still has error
}
}
At this point we still have that error, but when we call c, we get a function which has the right arguments based on whether we gave it a or b.
const cA = c(a); // type: (a: string, b: number) => void
cA("", 0);
const cB = c(b); // type: (a: string) => void
cB("");
As for the error, it has to do with what it means for a function to extend another function. Try changing F extends Func to F extends FuncA and F extends FuncB to see what happens. With F extends FuncB we get an error on c(a), but with F extends FuncA we don't get an error on c(b). Huh?
If you think about it in terms of a callback it makes sense. It's ok to pass a function that requires less arguments than expected, but not ok to pass one that requires more. But we are the ones implementing the callback so this creates a problem for us. If we extend type Func with a function that has no arguments, the empty array from Parameters<F> isn't sufficient to call either type.
We have to make our generic depend on the arguments instead.
type AP = Parameters<FuncA> // type: [a: string, b: number]
type BP = Parameters<FuncB> // type: [a: string]
type Args = AP | BP;
const c = <A extends Args>(func: (...args: A) => void) => {
return (...args: A) => {
func(...args) // no error
}
}
Typescript Playground Link
If you're ok with the decorated function being any function, you could do:
const c = <T extends (...a: any) => any>(func: T) => {
// do something here...
return (...args: Parameters<typeof func>): ReturnType<T> => {
return func(...args);
}
}
Calling it would look like
c<typeof a>(a)('a', 2)
I've got this section of code:
class Main {
static inline function difference(a:Int, b:Int, ?f:(Int, Int) -> Int):Int {
if (f == null) {
f = (a, b) -> a - b;
}
return f(a, b);
}
static function main() {
trace(difference(42, 37));
trace(difference(42, 37, (a, b) -> a - b));
}
}
Which, when I compile using haxe --main Main, fails with this error:
Main.hx:11: characters 15-50 : Cannot modify a closure parameter inside inline method
Main.hx:11: characters 15-50 : For function argument 'v'
If I change Main.difference to not be inline, this error doesn't come up and everything compiles fine.
Why does this error occur?
Edit: I've found out I can also assign the argument to a variable first, and then pass the variable to Main.difference, like this:
static function main() {
var f = (a, b) -> a - b;
trace(difference(42, 37, f));
}
Which works fine with Main.difference being inlined. How does assigning the function to a variable first change things though?
This is related to how inline functions are unwrapped by the compiler. Let us take a simpler variant of your code:
class HelloWorld {
static inline function difference(a:Int, b:Int, ?f:(Int, Int) -> Int):Int {
return f(a, b);
}
static function main() {
trace(difference(42, 37, (a, b) -> a - b));
}
}
When disabling optimizations, this will yield the following JavaScript:
HelloWorld.main = function() {
console.log("HelloWorld.hx:14:",(function(a,b) {
return a - b;
})(42,37));
};
So the body of difference has been incorporated into main using a JavaScript closure. My best guess for what is happnening in your exact case is something like this:
HelloWorld.main = function() {
var v = function(a,b) {
return a - b;
}
console.log("HelloWorld.hx:14:", (function(a,b) {
if (v == null) {
v = function(a, b) {
return a - b;
}
}
return v(a, b);
})(42, 37));
};
This alters the value of v, which exists outside of difference, which has been automatically placed there as a binding for the anonymous lambda. This is what the compiler is trying to avoid. This would not be the end of the world in your case, but in general this is bad and would lead to issues in many programs.
There is a way to inline this code perfectly by hand without this, but I think that there is some weirdness surrounding how annonymous lambdas are currently handled. The situation may improve in the future.
When you explicitly defined f in main, the compiler is intelligent enough to rename the nested f as f1, which is why the issue does not occur:
HelloWorld.main = function() {
var f = function(a,b) {
return a - b;
};
var f1 = f;
if(f1 == null) {
f1 = function(a,b) {
return a - b;
};
}
console.log("HelloWorld.hx:14:",f1(42,37));
};
But this would also work if the inline part of this function is important to you:
class HelloWorld {
static inline function difference(a:Int, b:Int, ?f:(Int, Int) -> Int):Int {
var h = f;
if (h == null) {
h = (a, b) -> a - b;
}
return h(a, b);
}
static function main() {
trace(difference(42, 37, (a, b) -> a - b));
}
}
I want to implement the interface shown below. I don't know how to begin. Can someone show me how the functions should be implemented?
package interval
package main
type Interval interface {
contains(r float64) bool // if r is in x, then true
average(Y Intervall) (Intervall, error)
String() string //cast interval"[a,b]" to [a,b]
completecontains(Y Intervall) bool //if y is completely in x, give true
New(a, b float64) Intervall
//var a int
}
type Complex struct {
first int
}
func (c Complex) contains(r float64) bool {
if a <= r <= b {
return true
} else {
return false
}
}
func (c Complex) String() string {
return "a"
}
func (c Complex) length() float64 {
return 2.3
}
func main() {
}
I can't really tell what you are actually trying to do here, but there were several issues with the code
a and b were not defined, I added them to complex to get it to compile
a <= r <= b is not valid in go, changed that
You had a main, so I assume that you meant this to be the runnable app. Package needs to be called "main" for it to be directly runnable.
May not be what you want, but it now compiles and runs (but doesn't do anything since main is empty)
Here it is on play
package main
//import "fmt"
type Intervall interface {
contains(r float64) bool // if r is in x, then true
average(Y Intervall) (Intervall, error)
String() string //cast interval"[a,b]" to [a,b]
completecontains(Y Intervall) bool //if y is completely in x, give true
New(a, b float64) Intervall
}
type Complex struct {
first int
a float64
b float64
}
func (c Complex) contains(r float64) bool {
if c.a <= r && r <= c.b {
return true
} else {
return false
}
}
func (c Complex) String() string {
return "a"
}
func (c Complex) length() float64 {
return 2.3
}
func main() {
}
Not sure why the concrete interval is called "Complex" or what the average of two intervals might be, but this is as close as I can get. Also, not sure what the benefit of using an interface is here.
http://play.golang.org/p/sxFRkJZCFa
package main
import "fmt"
type Interval interface {
Contains(r float64) bool
Average(y Interval) (Interval, error)
String() string
CompletelyContains(y Interval) bool
CompletelyContainedBy(y Interval) bool
}
type Complex struct {
a, b float64
}
func (c Complex) Contains(r float64) bool {
return c.a <= r && r <= c.b
}
func (c Complex) Average(y Interval) (Interval, error) {
return nil, fmt.Errorf("What the heck is the average of two intervals?")
}
func (c Complex) CompletelyContains(y Interval) bool {
return y.CompletelyContainedBy(c)
}
func (c Complex) CompletelyContainedBy(y Interval) bool {
return y.Contains(c.a) && y.Contains(c.b)
}
func (c Complex) String() string {
return fmt.Sprintf("[%v,%v]", c.a, c.b)
}
func main() {
var x Interval = Complex{a: 1, b: 5.1}
var y Interval = Complex{a: 1.3, b: 5}
fmt.Println("x contains 3:", x.Contains(3))
fmt.Println("x completely contains y:", x.CompletelyContains(y))
avg, err := x.Average(y)
fmt.Println("Average of x and y:", avg, "with error:", err)
fmt.Println("x:", x)
}
Edit: Here's a sillily complex way of implementing "Average" the way you want it. The complexity comes from avoiding directly accessing y.a and y.b, which would defeat the purpose of using an interface (if there is one).
http://play.golang.org/p/Tc5YCciLWq
After creating a struct like this:
type Foo struct {
name string
}
func (f Foo) SetName(name string) {
f.name = name
}
func (f Foo) GetName() string {
return f.name
}
How do I create a new instance of Foo and set and get the name?
I tried the following:
p := new(Foo)
p.SetName("Abc")
name := p.GetName()
fmt.Println(name)
Nothing gets printed, because name is empty. So how do I set and get a field inside a struct?
Working playground
Commentary (and working) example:
package main
import "fmt"
type Foo struct {
name string
}
// SetName receives a pointer to Foo so it can modify it.
func (f *Foo) SetName(name string) {
f.name = name
}
// Name receives a copy of Foo since it doesn't need to modify it.
func (f Foo) Name() string {
return f.name
}
func main() {
// Notice the Foo{}. The new(Foo) was just a syntactic sugar for &Foo{}
// and we don't need a pointer to the Foo, so I replaced it.
// Not relevant to the problem, though.
p := Foo{}
p.SetName("Abc")
name := p.Name()
fmt.Println(name)
}
Test it and take A Tour of Go to learn more about methods and pointers, and the basics of Go at all.
Setters and getters are not that idiomatic to Go.
Especially the getter for a field x is not named GetX
but just X.
See http://golang.org/doc/effective_go.html#Getters
If the setter does not provide special logic, e.g.
validation logic, there is nothing wrong with exporting
the field and neither providing a setter nor a getter
method. (This just feels wrong for someone with a
Java background. But it is not.)
For example,
package main
import "fmt"
type Foo struct {
name string
}
func (f *Foo) SetName(name string) {
f.name = name
}
func (f *Foo) Name() string {
return f.name
}
func main() {
p := new(Foo)
p.SetName("Abc")
name := p.Name()
fmt.Println(name)
}
Output:
Abc
It would seem that GPathResult returns a list of nodes which is the same for each iteration. How can I insert nodes from one iteration and find them in the next, as shown in the example below?
def messageNodes = [] as HashSet
def inputRoot = new XmlSlurper().parse(xmlFile)
inputRoot.testsuite.list().each { suiteNode ->
suiteNode.children().list().each { caseNode ->
caseNode.children().list().each { messageNode ->
messageNodes << messageNode
}
}
}
inputRoot.testsuite.list().each { suiteNode ->
suiteNode.children().list().each { caseNode ->
caseNode.children().list().each { messageNode ->
assert messageNodes.contains(message)
}
}
}
That code isn't inserting nodes... But as it stands (trying to find nodes are the same between scans), it won't work either due to the way XmlSlurper works...
When you call children() on a GPathResult, you end up with an iterator that returns new instances of NodeChild. Because these are new instances, they cannot be compared to the last time you saw them (as their hashcode will be different)
If you change your code to use XmlParser like so:
def messageNodes = []
def inputRoot = new XmlParser().parse(xmlFile)
inputRoot.testsuite.'*'.'*'.each { messageNode ->
messageNodes << messageNode
}
inputRoot.testsuite.'*'.'*'.each { messageNode ->
println messageNode.hashCode()
assert messageNodes.contains(messageNode)
}
I believe it works as you'd expect (I had to guess at your xml format though, as you didn't show us what it was in the question)
As an addition, you can change the lines
inputRoot.testsuite.'*'.'*'.each { messageNode ->
messageNodes << messageNode
}
to
messageNodes.addAll( inputRoot.testsuite.'*'.'*' )
for the same functionality...
It should also be noted that XmlSlurper doesn't store internal state in a navigable way, so if you add nodes, you cannot find them unless you write the xml out and read it back in. If this is the sort of thing you're aiming for, XmlParser is probably also the better route