REPL Problems


(Toni Suter) #1

Hi

I am trying to use Swift in a Jupyter Notebook with the following Kernel: https://github.com/rayh/iSwift. This kernel seems to use the Swift REPL to evaluate the user's code. That works well in some cases, but there are a few problems. For example, consider the following example:

struct S: Equatable { 
    static func ==(lhs: S, rhs: S) -> Bool { 
        return false 
    } 
} 

If this code is evaluated in a REPL more than one time, it fails with the following error:

error: 'S' is ambiguous for type lookup in this context

So it seems like there are now multiple versions of the type S. In a Jupyter Notebook it is very common that a cell is executed multiple times.

Is there some way to "clear the history" of the REPL without restarting it? Or is there a better solution?


(Ben Rimmington) #2

You could use a do statement, for local types and functions:

do {
    struct S: Equatable {
        static func ==(lhs: S, rhs: S) -> Bool {
            return false
        }
    }
}

(Toni Suter) #3

Thanks for your response! I think that could be a possible solution. My Jupyter notebook contains Swift exercises that consist of multiple steps each of which is displayed in a separate cell. If I wrap each cell in a do {} block, I can't access variables / functions / types that were declared in a previous cell. But maybe I just have to use one larger cell for each exercise that contains all the steps for that exercise. With the do {} block I could then at least execute the cell multiple times.

Another issue that I see with this approach is that some things (e.g., extensions, imports, operator declarations) need to be declared at file scope. But I can probably avoid those features in my use case.


(Toni Suter) #4

Here's another issue:

do {
    struct S {
        var x: Int
        
        static func +(lhs: S, rhs: S) -> S {
            return S(x: lhs.x + rhs.x)
        }
    }
	
    let s1 = S(x: 1)
    let s2 = S(x: 2)
    print(s1 + s2)      // error: binary operator '+' cannot be applied to two 'S' operands
}

When you overload an operator for a local type the compiler can't find the corresponding operator function. Seems like the == operator only works because of the Equatable auto-synthesis:

do {
	struct S: Equatable {
		static func ==(lhs: S, rhs: S) -> Bool {
			return false
		}
	}
	
	print(S() == S())	// true (but should be false)
}

I filed a bug here: https://bugs.swift.org/browse/SR-8872