I am trying to figure out what instance variables do not show up in auto completion in an IPython or Jupyter notebook. For example, if I have the class below:
class A:
def __init__(self, var_a: int):
self.var_a = var_a
and I define a class B that takes an instance of A at initialization, it seems like autocompletion does not look through to the definition of class A to see that it has a var_a instance attribute.
class B:
def __init__(self, var_b: A):
self.var_b = var_b
def func(self):
self.var_b.
I do not get any type hints if I press tab after the last period in the snippet above. Pylance (through the VS Code Python extension) and PyCharm both show autocompletion for self.var_b.var_a. Is there a way to configure either IPython or the code annotations so that autocompletion will also work in IPython?
Using IPython 8.4.0
Tried %config Completer.use_jedi = True in the first notebook cell which did not help.
Explicitly annotating the namespaces of the classes should work:
class A:
var_a: int
def __init__(self, var_a: int) -> None:
self.var_a = var_a
class B:
var_b: A
def __init__(self, var_b: A) -> None:
self.var_b = var_b
It doesn't get more explicit than that. If this code doesn't lead to proper type inference/auto-suggestions, that should be considered a bug.
Related
I am trying to create a type class inside IntelliJ Scala Worksheet. So I started with trait like this
trait Show[A] {
def show(a : A) : String
}
and created a companion object
object Show {
def show[A](a: A)(implicit sh: Show[A]) = sh.show(a)
implicit val intCanShow: Show[Int] =
new Show[Int] {
def show(int: Int): String = s"int $int"
}
}
When I try
println(Show.show(20))
I get this error.
Error:(50, 26) could not find implicit value for parameter sh: Show[Int]
println(Show.show(20))
But when I take the intCanShow out of the object Show, it works fine. Why cannot scala acess the the implicit inside the object?
Implicit resolution tries companion objects so your code seems ok. However for an object to become a companion it must satisfy the following two requirements
A companion object is an object with the same name as a class or trait, and
is defined in the same source file as the associated class or trait.
The following warning means the second requirement is not satisfied:
defined object Show
warning: previously defined trait Show is not a companion to object Show.
Companions must be defined together; you may wish to use :paste mode for this.
To satisfy second requirement we have to use Plain evaluation model in Scala Worksheet, or :paste mode in Scala REPL.
Scala Worksheet Plain evaluation model
To define a companion object in IntelliJ Scala Worksheet change Run type to Plain like so
Show Worksheet Settings
Select tab Settings for *.sc
Change Run type from REPL to Plain
Scala REPL paste mode
As per #jwvh suggestion, make sure to enter paste mode
If a class or object has a companion, both must be defined in the same
file. To define companions in the REPL, either define them on the same
line or enter :paste mode.
as demonstrated here.
Your example appears to work as expected when run as a scala script.
With the following in a file named test.sh and marked executable
#!/usr/bin/env scala
trait Show[A] {
def show(a : A) : String
}
object Show {
def show[A](a: A)(implicit sh: Show[A]) = sh.show(a)
implicit val intCanShow: Show[Int] =
new Show[Int] {
def show(int: Int): String = s"int $int"
}
}
println(Show.show(20))
I observe
bash-3.2$ ./test.sh
int 20
Loading a ficus configuration like
loadConfiguration[T <: Product](): T = {
import net.ceedubs.ficus.readers.ArbitraryTypeReader._
import net.ceedubs.ficus.Ficus._
val config: Config = ConfigFactory.load()
config.as[T]
fails with:
Cannot generate a config value reader for type T, because it has no apply method in a companion object that returns type T, and it doesn't have a primary constructor
when instead directly specifying a case class instead of T i.e. SomeClass it works just fine. What am I missing here?
Ficus uses the type class pattern, which allows you to constrain generic types by specifying operations that must be available for them. Ficus also provides type class instance "derivation", which in this case is powered by a macro that can inspect the structure of a specific case class-like type and automatically create a type class instance.
The problem in this case is that T isn't a specific case class-like type—it's any old type that extends Product, which could be something nice like this:
case class EasyToDecode(a: String, b: String, c: String)
But it could also be:
trait X extends Product {
val youWillNeverDecodeMe: String
}
The macro you've imported from ArbitraryTypeReader has no idea at this point, since T is generic here. So you'll need a different approach.
The relevant type class here is ValueReader, and you could minimally change your code to something like the following to make sure T has a ValueReader instance (note that the T: ValueReader syntax here is what's called a "context bound"):
import net.ceedubs.ficus.Ficus._
import net.ceedubs.ficus.readers.ValueReader
import com.typesafe.config.{ Config, ConfigFactory }
def loadConfiguration[T: ValueReader]: T = {
val config: Config = ConfigFactory.load()
config.as[T]
}
This specifies that T must have a ValueReader instance (which allows us to use .as[T]) but says nothing else about T, or about where its ValueReader instance needs to come from.
The person calling this method with a concrete type MyType then has several options. Ficus provides instances that are automatically available everywhere for many standard library types, so if MyType is e.g. Int, they're all set:
scala> ValueReader[Int]
res0: net.ceedubs.ficus.readers.ValueReader[Int] = net.ceedubs.ficus.readers.AnyValReaders$$anon$2#6fb00268
If MyType is a custom type, then either they can manually define their own ValueReader[MyType] instance, or they can import one that someone else has defined, or they can use generic derivation (which is what ArbitraryTypeReader does).
The key point here is that the type class pattern allows you as the author of a generic method to specify the operations you need, without saying anything about how those operations will be defined for a concrete type. You just write T: ValueReader, and your caller imports ArbitraryTypeReader as needed.
I am trying to initialize a derived class from text file input. A simple example of what I am trying to do:
file.txt:
1
2
main.py:
class Base:
def __init__(self, val1):
self.val1 = val1
def input_from_text(cls, init_deque):
#return cls(init_deque.popleft())
class Derived(Base):
def __init__(self, val1, val2):
Base.__init__(self, val1)
self.val2 = val2
def input_from_text(cls, init_deque):
#initialize base and derived here and return derived
def main(argv=None):
initialized_derived = Derived.input_from_text(deque(open("file.txt")))
assert initialized_derived.val1 is 1
assert initialized_derived.val2 is 2
Is there a good way to do this? Basically looking for something similar to what you would find in C++ with:
//calls operator>>(Base) then operator>>(Derived)
cin >> initialized_derived;
This way each class is nicely encapsulated and the base/derived classes don't need to know anything about each other (excepting __init__ which knows the number of args base takes).
Just realized that I was going about this the wrong way. Simple fix is to do something like:
class Base:
def __init__(self):
pass
def input_from_text(self, init_deque):
self.val1 = init_deque.popleft()
class Derived(Base):
def __init__(self):
Base.__init__(self)
def input_from_text(self, init_deque):
Base.input_from_text(self, init_deque)
self.val2 = init_deque.popleft()
I have written JDBC select and insert mapping using scala macro functionality.
gist
As you can see in the gist there is a lot of duplicated code...
I can't extract case classes ClassInfo and ColumnInfo outside of method scope because of c.universe._ import because I'm using c.Type.
I have tried using scala.reflect.runtime.universe._ but then I get some mirror exceptions and suddenly type comparison doesn't work anymore - I don't get ClassSymbol anymore but SynchronizedClassSymbol and I have to compare it using fullName and it suddenly get's very messy...
So my question is:
I would like to refactor:
case class ClassInfo
case class ColumnInfo
mapGet
mapSet
def getBaseClass(tp: c.Type): c.Type
def getClassInfo(tp: c.Type): Option[ClassInfo]
def getConstructorParameters(tp: c.Type): Seq[ColumnInfo]
def selectFullTermName(sym: c.Symbol): c.Tree
Outside of methods selectImpl and insertImpl but I just don't know how :(
I tried for example with method
def getBaseClass(tp: c.Type): c.Type
To put it outside like this:
def getBaseClass(c: whitebox.Context)(tp: c.Type) = {
import c.universe._
if (tp.baseClasses.map(_.fullName).contains(symbolOf[Option[_]].fullName))
tp.typeArgs.head
else
tp
}
But then where I call it like
getBaseClass(c)(x.typeSignature)
I get an error:
Type missmatch, expected: c.Type, actual: whitebox.Context#Type
And it drives me crazy =)
I'm quite new at Scala so if you have any other comments about how to write macros - if I have made any mistakes - please let me know=)
Turns out it works like this:
def getBaseClass(c: whitebox.Context)(tp: c.Type) = {
import c.universe._
if (tp.baseClasses.map(_.fullName).contains(symbolOf[Option[_]].fullName))
tp.typeArgs.head
else
tp
}
It compiles but IntelliJ reports error:
Type missmatch, expected: c.Type, actual: whitebox.Context#Type
So it's a IDE bug =)
I am writing a Scala class that implements a 2-dimensional matrix of arbitrary objects. I need the class to be more specialized than nested pair of IndexedSeq objects, but extending a collections class is overkill, so I'm writing my own. In order to return the correct type from methods in my matrix class, I am using the implicit builder idiom, but at runtime I get a "could not find implicit value for parameter" error which I don't understand.
A stripped-down version of my matrix class looks like this.
trait MatrixBuilder[V, M <: Matrix[V]] {
def apply(values: IndexedSeq[IndexedSeq[V]]): M
}
abstract class Matrix[V](values: IndexedSeq[IndexedSeq[V]]) extends Function2[Int, Int, V] {
def apply(row: Int, col: Int): V = values(row)(col)
def set[M <: Matrix[V]](row: Int, col: Int, value: V)(implicit builder: MatrixBuilder[V, M]): M =
builder(values.updated(row, values(row).updated(col, value)))
}
case class IntMatrix(values: IndexedSeq[IndexedSeq[Int]]) extends Matrix[Int](values)
object IntMatrix {
def apply(n: Int) = new IntMatrix(IndexedSeq.fill(n, n)(0))
implicit object IntMatrixBuilder extends MatrixBuilder[Int, IntMatrix] {
def apply(values: IndexedSeq[IndexedSeq[Int]]) = IntMatrix(values)
}
}
I want the set function to set the specified cell then return a new matrix of the correct type. So I expect IntMatrix(2).set(0,0,5) to return an IntMatrix object with zeros in all cells except (0,0), where it should have a 5. Instead I get the following error at runtime.
error: could not find implicit value for parameter builder: MatrixBuilder[Int,M]
IntMatrix(2).set(0,0,5)
What am I doing wrong here?
As pedrofurla notes below, the code does work in the REPL if you first run the line import IntMatrix._. And looking at the collections documentation, there appear to be similar import statements in source code using builders. I tried adding one to my IntMatrix class.
case class IntMatrix(values: IndexedSeq[IndexedSeq[Int]]) extends Matrix[Int](values) {
import IntMatrix._
}
But this has no effect. (In fact my IDE IntelliJ flags this as an unused import statement.)
For comparison I copied over the RNA sequence example from the collections documentation linked above verbatim. There the import RNA._ line is not marked as superfluous and all operations return the correct type. If the answer is that I need to add an import IntMatrix._, I can't figure out where to put it.
This little code worked here:
scala> import IntMatrix._
import IntMatrix._
scala> IntMatrix(2).set(0,0,5)
res1: Mat.IntMatrix = <function2>
Implicit parameters are filled by compiler in the call site, so they have to be available in the scope set is being invoked.