Scala Recipes
Table of Contents
1 Scala Recipes - Examples about integration with Java
1.1 Show Java Properties
scala> System.getProperty ("java.vm.vendor") res2: String = Oracle Corporation scala> System.getProperty ("java.home") res3: String = /usr/lib/jvm/java-8-openjdk/jre scala> List("java.vm.vendor", "java.home", "java.runtime.name", "java.vm.name").map(System.getProperty) res4: List[String] = List(Oracle Corporation, /usr/lib/jvm/java-8-openjdk/jre, OpenJDK Runtime Environment, OpenJDK 64-Bit Server VM) scala> val xs = List("java.vm.vendor", "java.home", "java.runtime.name", "java.vm.name") xs: List[String] = List(java.vm.vendor, java.home, java.runtime.name, java.vm.name) scala> xs.foreach(p => println ("%s\t%s".format(p, System.getProperty(p)))) java.vm.vendor Oracle Corporation java.home /usr/lib/jvm/java-8-openjdk/jre java.runtime.name OpenJDK Runtime Environment java.vm.name OpenJDK 64-Bit Server VM
1.2 Java Reflection
1.2.1 Show Class Method given a class name
See: Reflection
scala> Class.forName("java.io.File").getDeclaredMethods().take(10).foreach(println) public boolean java.io.File.equals(java.lang.Object) public java.lang.String java.io.File.toString() public int java.io.File.hashCode() public int java.io.File.compareTo(java.lang.Object) public int java.io.File.compareTo(java.io.File) public java.lang.String java.io.File.getName() public long java.io.File.length() public java.lang.String java.io.File.getParent() public boolean java.io.File.isAbsolute() public java.lang.String java.io.File.getCanonicalPath() throws java.io.IOException def show_class_methods (classname: String) { Class .forName(classname) .getDeclaredMethods() .foreach(println) } show_class_methods: (classname: String)Unit scala> show_class_constructors("javax.swing.JFrame") protected void javax.swing.JFrame.frameInit() protected javax.swing.JRootPane javax.swing.JFrame.createRootPane() protected void javax.swing.JFrame.processWindowEvent(java.awt.event.WindowEvent) public void javax.swing.JFrame.setDefaultCloseOperation(int) public int javax.swing.JFrame.getDefaultCloseOperation() public void javax.swing.JFrame.setTransferHandler(javax.swing.TransferHandler) public javax.swing.TransferHandler javax.swing.JFrame.getTransferHandler() public void javax.swing.JFrame.setJMenuBar(javax.swing.JMenuBar) public javax.swing.JMenuBar javax.swing.JFrame.getJMenuBar() ... def show_class_constructors (classname: String) { Class .forName(classname) .getDeclaredConstructors() .foreach(println) } scala> show_class_constructors("java.io.File") public java.io.File(java.lang.String,java.lang.String) public java.io.File(java.lang.String) private java.io.File(java.lang.String,java.io.File) public java.io.File(java.io.File,java.lang.String) public java.io.File(java.net.URI) private java.io.File(java.lang.String,int) scala> Class.forName("java.io.File").getDeclaredFields().foreach(println) private static final java.io.FileSystem java.io.File.fs private final java.lang.String java.io.File.path private transient java.io.File$PathStatus java.io.File.status private final transient int java.io.File.prefixLength public static final char java.io.File.separatorChar public static final java.lang.String java.io.File.separator public static final char java.io.File.pathSeparatorChar public static final java.lang.String java.io.File.pathSeparator private static final long java.io.File.PATH_OFFSET private static final long java.io.File.PREFIX_LENGTH_OFFSET private static final sun.misc.Unsafe java.io.File.UNSAFE private static final long java.io.File.serialVersionUID private transient volatile java.nio.file.Path java.io.File.filePath static final boolean java.io.File.$assertionsDisabled
1.2.2 Show Object Methods
def showObjectMethods(obj: Any) = { obj.getClass().getDeclaredMethods().foreach(println) }
Test:
scala> import scala.io.Source import scala.io.Source scala> import java.net.URL import java.net.URL scala> val url = new URL("http://www.httpbin.org/get") url: java.net.URL = http://www.httpbin.org/get scala> showObjectMethods(url) public boolean java.net.URL.equals(java.lang.Object) public java.lang.String java.net.URL.toString() public synchronized int java.net.URL.hashCode() public final java.io.InputStream java.net.URL.openStream() throws java.io.IOException private synchronized void java.net.URL.readObject(java.io.ObjectInputStream) throws java.io.IOException,java.lang.ClassNotFoundException private synchronized void java.net.URL.writeObject(java.io.ObjectOutputStream) throws java.io.IOException void java.net.URL.set(java.lang.String,java.lang.String,int,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String) void java.net.URL.set(java.lang.String,java.lang.String,int,java.lang.String,java.lang.String) private java.lang.Object java.net.URL.readResolve() throws java.io.ObjectStreamException public java.lang.String java.net.URL.getPath() public java.net.URI java.net.URL.toURI() throws java.net.URISyntaxException public java.lang.String java.net.URL.getAuthority() public java.lang.String java.net.URL.getQuery() public java.net.URLConnection java.net.URL.openConnection(java.net.Proxy) throws java.io.IOException public java.net.URLConnection java.net.URL.openConnection() throws java.io.IOException public java.lang.String java.net.URL.getProtocol() public java.lang.String java.net.URL.getFile() public java.lang.String java.net.URL.getHost() ...
1.2.3 Show Object Public Methods
import java.lang.reflect.Modifier def showObjPublicMethods (obj: Any) { for (m <- url.getClass().getDeclaredMethods() if Modifier.isPublic(m.getModifiers) ) println(m) }
Example:
scala> import java.net.URL import java.net.URL scala> showObjPublicMethods(url) public boolean java.net.URL.equals(java.lang.Object) public java.lang.String java.net.URL.toString() public synchronized int java.net.URL.hashCode() public final java.io.InputStream java.net.URL.openStream() throws java.io.IOException public java.lang.String java.net.URL.getPath() public java.net.URI java.net.URL.toURI() throws java.net.URISyntaxException public java.lang.String java.net.URL.getAuthority() public java.lang.String java.net.URL.getQuery() public java.net.URLConnection java.net.URL.openConnection(java.net.Proxy) throws java.io.IOException public java.net.URLConnection java.net.URL.openConnection() throws java.io.IOException public java.lang.String java.net.URL.getProtocol() public java.lang.String java.net.URL.getFile() public java.lang.String java.net.URL.getHost() public java.lang.String java.net.URL.getUserInfo() public int java.net.URL.getPort() public int java.net.URL.getDefaultPort() public java.lang.String java.net.URL.getRef() public boolean java.net.URL.sameFile(java.net.URL) public java.lang.String java.net.URL.toExternalForm() public final java.lang.Object java.net.URL.getContent(java.lang.Class[]) throws java.io.IOException public final java.lang.Object java.net.URL.getContent() throws java.io.IOException public static void java.net.URL.setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory)
1.2.4 Show Object's Public Method Names
import java.lang.reflect.Modifier def showObjMethodNames (obj: Any){ for (m <- obj.getClass().getDeclaredMethods() if Modifier.isPublic(m.getModifiers) ) println(m.getName()) }
Example:
scala> showObjMethodNames(url) equals toString hashCode openStream getPath toURI getAuthority getQuery openConnection openConnection getProtocol getFile getHost ...
1.3 GUI - Graphical User Interface (Java Swing)
1.3.1 Messagebox
- File: src/messageBox.scala
def messageBox (title: String, content: String) { javax.swing.JOptionPane.showMessageDialog ( null, content, title, javax.swing.JOptionPane.PLAIN_MESSAGE ) } messageBox("Information", "Download of file animation.jar completed")
1.3.2 Password Dialog
- File: src/passwordGui.scala
import javax.swing.{JFrame, JLabel, JButton, JPanel, JPasswordField} def getPassword(passwd: javax.swing.JPasswordField) = new String(passwd.getPassword()) /// Register callback function /// def onClick(button: JButton) (handler: => Unit) = { button.addActionListener( new java.awt.event.ActionListener(){ def actionPerformed(evt: java.awt.event.ActionEvent) = { handler } } ) } def onWindowExit(frame: javax.swing.JFrame) (handler: => Unit) = { frame.addWindowListener( new java.awt.event.WindowAdapter(){ override def windowClosing(evt: java.awt.event.WindowEvent) = { handler } }) } val frame = new JFrame("Scala password entry") frame.setSize(400, 200) frame.setLayout(new java.awt.GridLayout(2, 1)) // frame.setLayout() val panel = new JPanel(new java.awt.FlowLayout()) val label = new JLabel("Password") val passwd = new JPasswordField(10) val btn = new JButton("Login") val status = new JLabel("Safe closed") passwd.setEchoChar('*') panel.add(label) panel.add(passwd) panel.add(btn) frame.add(panel) frame.add(status) frame.setVisible(true) //--------- Event Handling ---------- def checkPassword( passwd: String, input: String, okHanlder: () => Unit, errHandler: () => Unit ) = { if (input == passwd) okHanlder() else errHandler() } onClick(btn){ println("I was clicked")} onClick(btn) { val pass = getPassword(passwd) if (pass == "thepassword") println("Safe opened") else println("Error: Wrong password") } onClick(btn){ checkPassword( "thepassword" ,getPassword(passwd) ,() => status.setText("Safe opened. Ok") ,() => status.setText("Error: Wrong password") )} onWindowExit(frame){ System.exit(0) }
1.3.3 List View Dialog
The function listView is useful for data vizualization of lists, files, numbers and son on.
- File: src/listViewGui.scala
/// Function to visualize data in List View Mode /// def listView(elements: Array[String]){ val frame = new javax.swing.JFrame("List Data View") val model = new javax.swing.DefaultListModel[String]() val list = new javax.swing.JList(model) val scroll = new javax.swing.JScrollPane(list) frame.add(scroll) elements.foreach(model.addElement) frame.setSize(300, 400) frame.setVisible(true) } def listFiles(path: String) = { (new java.io.File(path)) .listFiles() .map(_.toString) }
Show the files of directory etc
listView(listFiles("/etc"))
Show java properties
import scala.collection.JavaConverters._ val properties = System.getProperties().asScala.toArray.map { case (k, v) => k + " = " + v } listView(properties)
1.3.4 Text View Dialog
def textView(file: String) = { val frame = new javax.swing.JFrame("Text View App") val textArea = new javax.swing.JTextArea() val scroll = new javax.swing.JScrollPane(textArea) textArea.setText("") frame.add(scroll) frame.setSize(300, 400) frame.setVisible(true) val text = scala.io.Source.fromFile(file).mkString textArea.setText(text) } scala> textView("/etc/protocols")
1.3.5 Clock Display
def runTimer(interval: Int, taskFn: () => Unit) = { val task = new java.util.TimerTask() { def run() { taskFn() } } val timer = new java.util.Timer() // Run the task every 1 second interval (or 1000 milli seconds) timer.schedule(task, 1, interval) timer } def currentTime() = { java.time.LocalDateTime.now.toString } val frame = new javax.swing.JFrame("Java Clock App") val label = new javax.swing.JLabel("") frame.add(label) frame.setSize(375, 76) frame.setVisible(true) runTimer(1000, () => label.setText(currentTime()))
1.4 Http Get Request
Java Code - https://www.mkyong.com/java/how-to-send-http-request-getpost-in-java/
def httpGetRead(url: String) = { val obj = new java.net.URL(url) val conn = obj.openConnection().asInstanceOf[java.net.HttpURLConnection] conn.setRequestMethod("GET") conn.setRequestProperty("User-Agent", "Scala browser") val respCode = conn.getResponseCode() val bf = new java.io.BufferedReader( new java.io.InputStreamReader(conn.getInputStream())) val out = Stream.continually(bf.readLine()) .takeWhile(_!=null) .mkString("\n") out } scala> httpGetRead("http://www.httpbin.org/get") res24: String = { "args": {}, "headers": { "Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2", "Connection": "close", "Host": "www.httpbin.org", "User-Agent": "Scala browser" }, "origin": "186.212.135.2", "url": "http://www.httpbin.org/get" }
1.5 Using a jar files or java library
Example: Using JFreeChart chart library.
- Official web site: http://www.jfree.org/jfreechart/
- https://mvnrepository.com/artifact/jfree/jfreechart/1.0.13
- Download: http://repo1.maven.org/maven2/org/jfree/
- Tutorial: JFreeChart Tutorial
- Download JFreeChart
$ mkdir ~/test && cd ~/test $ mkdir lib # Download jars $ curl -o lib/jfreechart.jar -L http://repo1.maven.org/maven2/org/jfree/jfreechart/1.0.19/jfreechart-1.0.19.jar $ curl -o lib/jcommon.jar -L http://repo1.maven.org/maven2/org/jfree/jcommon/1.0.23/jcommon-1.0.23.jar # Download this file to check dependencies $ curl -O http://repo1.maven.org/maven2/org/jfree/jfreechart/1.0.19/jfreechart-1.0.19.pom
- Start Scala REPL with:
$ scala -cp lib/jcommon.jar:lib/jfreechart.jar
or
$ scala Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_20). Type in expressions for evaluation. Or try :help. scala> :require lib/jcommon.jar Added '/home/archbox/test/lib/jcommon.jar' to classpath. scala> :require lib/jfreechart.jar Added '/home/archbox/test/lib/jfreechart.jar' to classpath.
- Plotting a pie chart. It was based on JFreeChart Tutorial.
File: src/jfreeChart1.scala
The lines below can be pasted in the Scala REPL and the user can and manipulate the chart objects and modify it interactively.
import org.jfree.chart.{ChartPanel, ChartFactory, JFreeChart, ChartUtilities} import org.jfree.data.general.DefaultPieDataset val dataset = new DefaultPieDataset() dataset.setValue("A", 75) dataset.setValue("B", 10) dataset.setValue("C", 10) dataset.setValue("D", 5) val chart = ChartFactory.createPieChart( "Sample Pie Chart", // Title dataset, // Dataset true, // Show legend true, // Tooltips on false ) // Save chart to a png file //--------------------------- ChartUtilities.saveChartAsPNG(new java.io.File("mychart.png"), chart, 500, 500) // Show Chart in a Java Swing Frame //-------------------------------------- val frame = new javax.swing.JFrame() frame.add(new ChartPanel(chart)) frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE) frame.setSize(693, 513) frame.setTitle("Sample Pie Chart") frame.setVisible(true)
It will display this chart:
- Running the file src/jfreeChart1.scala
# It will create the file jfreeChart1.jar $ scala -cp lib/jcommon.jar:lib/jfreechart.jar -save jfreeChart1.scala # The second time this command is run, it will run the file # jfreeChart1.jar that is a faster than run jfreeChart1.scala. $ scala -cp lib/jcommon.jar:lib/jfreechart.jar -save jfreeChart1.scala # The produced jar file can be run directly with Scala. $ scala -cp lib/jcommon.jar:lib/jfreechart.jar -save jfreeChart1.jar
- Building an uber jar or fat-jar for easier distribution and deployment. A fat is a jar file bundled with all dependencies and runt-time libraries which makes possible to run the jar-file without Scala or JFree chart available at the deployment machine.
This procedure uses the script: jar-tools.sh
$ jar-tools.sh -scala-build-jar out/jfreeChart1-fat.jar jfreeChart1.jar lib/* At directory /home/archbox/test/out/temp Extracting /home/archbox/test/lib/jcommon.jar Extracting /home/archbox/test/lib/jfreechart.jar Manifest Content META-INF/MANIFEST.MF Manifest-Version: 1.0 Scala-Compiler-Version: 2.11.8 Main-Class: Main Building fat-jar file ... added manifest adding: com/(in = 0) (out= 0)(stored 0%) adding: com/keypoint/(in = 0) (out= 0)(stored 0%) adding: com/keypoint/PngEncoder.class(in = 9079) (out= 4645)(deflated 48%) adding: library.properties(in = 187) (out= 135)(deflated 27%) adding: Main$$anon$1.class(in = 1967) (out= 1031)(deflated 47%) adding: Main.class(in = 556) (out= 469)(deflated 15%) adding: Main$.class(in = 570) (out= 372)(deflated 34%) ignoring entry META-INF/ ... ... ... ... ... ... ... ... ... ... ... ... ... ... adding: scala/Predef$StringFormat$.class(in = 2107) (out= 1010)(deflated 52%) adding: scala/Tuple5$.class(in = 1805) (out= 768)(deflated 57%) adding: scala/Function2$mcZJD$sp.class(in = 323) (out= 196)(deflated 39%) adding: scala/Char.class(in = 6084) (out= 3604)(deflated 40%) adding: scala/Float.class(in = 5382) (out= 3268)(deflated 39%) adding: scala/Enumeration$ValueSet$$anon$2.class(in = 1673) (out= 668)(deflated 60%) -------------------------------------- Built file: out/jfreeChart1-fat.jar Ok. Run it with $ java -jar out/jfreeChart1-fat.jar
The uber jar can be run by using the line below or by double clicking at the jar file if the system is configured properly:
$ java -jar out/jfreeChart1-fat.jar
This jar-file can be turned into a Unix executable with:
$ jar-tools.sh -jar-to-sh out/jfreeChart1-fat.jar out/jfreeChart1.sh Build jar-executable out/jfreeChart1.sh Run it with ./out/jfreeChart1.sh $ file out/jfreeChart1.sh out/jfreeChart1.sh: a /usr/bin/env sh script executable (binary data) $ head -n 3 out/jfreeChart1.sh #!/usr/bin/env sh java -jar $0 exit 0
It can be executed with:
$ ./out/jfreeChart1.sh
1.6 C# Delegates in Scala
1.6.1 Delegates in C#
C#'s delegate works in a similar way to C or C++ function pointers and can hold reference instance method, static method or lambda function.
Use cases:
- Implement callbacks
- Decouple classes: A class can call directly a method or static of another class without it implement any known interface. In addition to the indirect method call, delegates also allow lambda functions to be passed as arguments.
Examples in Mono (C# Shell):
- Point to static class method.
$ csharp Mono C# Shell, type "help;" for help Enter statements below. csharp> // Create a function pointer which can point to // any function of type: // // ==> double => double // (input) (output) //------------------------------------------------ csharp> public delegate double MathFunc(double x); csharp> csharp> double pi = 3.1415 // Create an empty delegate initially set to null csharp> MathFunc mfun; csharp> // ========= Supposed to fail throwing Null exception =========== // // csharp> mfun == null true csharp> csharp> mfun(pi) System.NullReferenceException: Object reference not set to an instance of an object at <InteractiveExpressionClass>.Host (System.Object& $retval) [0x00000] ... csharp> csharp> mfun.Invoke(pi) System.NullReferenceException: Object reference not set to an instance of an object // ========= Point to Math.Sin static method =========== // // csharp> mfun = Math.Sin csharp> csharp> mfun == null false csharp> // Ok - Supposed to return zero or very close to zero. csharp> mfun(pi) 9.26535896604903E-05 csharp> csharp> mfun.Invoke(pi) 9.26535896604903E-05 csharp> csharp> mfun(pi/2.0) 0.999999998926914 csharp> mfun.Invoke(pi/2.0) 0.999999998926914 // ========= Point to Math.Cos static method =========== // // csharp> mfun = Math.Cos // cos(pi) = cos(180 degrees) =~ -1 csharp> mfun(pi) -0.999999995707656 csharp> mfun.Invoke(pi) -0.999999995707656 // cos(pi/2) = cos(90 degrees) =~ 0 csharp> mfun(pi/2) 4.63267948799578E-05
Point to an instance's method.
// Linear Equation f(x) = a * x + b class LinFun{ private double _a = 0.0; private double _b = 0.0; public LinFun(double a, double b){ _a = a; _b = b; } public void SetA(double a){ _a = a; } public void SetB(double b){ _b = b; } public double Compute(double x){ return _a * x + _b; } } csharp> public delegate double MathFunc(double x); csharp> csharp> var linFun = new LinFun(3.0, 4.0); csharp> // Compute equation f(x) = 3 * x + 4 // csharp> mfun = linFun.Compute ; csharp> csharp> mfun(0.0) 4 csharp> mfun(1.0) 7 csharp> mfun(2.0) 10 csharp> mfun(3.0) 13 csharp> mfun(4.0) 16 csharp> // Compute y(x) = 2 * x + 0.0 // csharp> linFun.SetA(2.0) csharp> linFun.SetB(0.0) csharp> csharp> mfun(0.0) 0 csharp> mfun(1.0) 2 csharp> mfun(2.0) 4 csharp> mfun(4.0) 8 csharp> mfun.Invoke(1.0) 2 csharp> mfun.Invoke(2.0) 4 csharp> mfun.Invoke(3.0) 6 csharp>
Point static methods of a custom class:
class MathModule{ public static double Square(double x){ return x * x; } public static double Triple(double x){ return 3.0 * x; } } csharp> public delegate double MathFunc(double x); csharp> mfun = MathModule.Square csharp> mfun.Invoke(3.0) 9 csharp> mfun.Invoke(4.0) 16 csharp> mfun.Invoke(5.0) 25 csharp> csharp> mfun = MathModule.Triple csharp> mfun.Invoke(3.0) 9 csharp> mfun.Invoke(4.0) 12 csharp> mfun(5.0) 15 csharp>
Point to a lambda function (aka anonymous function):
csharp> mfun = x => 5.0 * x + 10.0 csharp> csharp> mfun = x => 5.0 * x + 10.0 csharp> csharp> mfun(0.0) 10 csharp> mfun(1.0) 15 csharp> mfun(2.0) 20 csharp> mfun(3.0) 25 csharp>
Decouple classes:
class TableBuilder{ private double _xmin = 0; private double _xmax = 10.0; private double _step = 1.0; public void SetRange(double xmin, double xmax, double step = 0.1){ _xmin = xmin; _xmax = xmax; _step = step; Console.WriteLine("Set xmin = {0} xmax = {1} step = {2} ", _xmin, _xmax, _step); } public void Show(MathFunc fn){ for(double x = _xmin; x < _xmax; x = x + _step){ Console.WriteLine("x = {0:F3}\ty={1:F3}", x, fn(x)); } } } csharp> var linFunService = new LinFun(4.0, 5.0) // Compute table for y(x) = 4.0 * x + 5.0 csharp> tableBuilder.Show(linFunService.Compute) x = 0.000 y=5.000 x = 1.000 y=9.000 x = 2.000 y=13.000 x = 3.000 y=17.000 x = 4.000 y=21.000 x = 5.000 y=25.000 x = 6.000 y=29.000 x = 7.000 y=33.000 x = 8.000 y=37.000 x = 9.000 y=41.000 csharp> // Compute table for y(x) = 3.0 * x + 4.0 csharp> linFunService.SetA(3.0) csharp> linFunService.SetB(0.0) csharp> csharp> tableBuilder.Show(linFunService.Compute) x = 0.000 y=0.000 x = 1.000 y=3.000 x = 2.000 y=6.000 x = 3.000 y=9.000 x = 4.000 y=12.000 x = 5.000 y=15.000 x = 6.000 y=18.000 x = 7.000 y=21.000 x = 8.000 y=24.000 x = 9.000 y=27.000 csharp> // Compute table for static method Sin of class Math. csharp> tableBuilder.Show(Math.Sin) x = 0.000 y=0.000 x = 1.000 y=0.841 x = 2.000 y=0.909 x = 3.000 y=0.141 x = 4.000 y=-0.757 x = 5.000 y=-0.959 x = 6.000 y=-0.279 x = 7.000 y=0.657 x = 8.000 y=0.989 x = 9.000 y=0.412 csharp> // Compute table using lambda function csharp> tableBuilder.Show(x => 2 * x + 3) x = 0.000 y=3.000 x = 1.000 y=5.000 x = 2.000 y=7.000 x = 3.000 y=9.000 x = 4.000 y=11.000 x = 5.000 y=13.000 x = 6.000 y=15.000 x = 7.000 y=17.000 x = 8.000 y=19.000 x = 9.000 y=21.000 csharp>
1.6.2 Delegates in Scala
A delegate in Scala can be just a variable of function type. As in C#, it can hold reference to instance methods, static methods and lambda functions.
Declare delegate type.
// C#: public delegate double MathFunc(double x) type MathFunc = Double => Double
Create delegate variable:
// Initialize with NULL -> Null is evil, but it will be used for the sake of testing // and experimentation. // scala> var mfun: MathFunc = null mfun: MathFunc = null // Approximate value of PI scala> val pi = 3.1415 pi: Double = 3.1415 scala> mfun(pi) java.lang.NullPointerException ... 28 elided
Point to lambda function:
//----- Point to Lambda Function ------------------------// // scala> mfun = x => 3.0 * x + 5.0 mfun: MathFunc = $$Lambda$1097/302990364@2407f1a8 scala> mfun(0.0) res13: Double = 5.0 scala> mfun(1.0) res14: Double = 8.0 scala> mfun(2.0) res15: Double = 11.0 scala> val someLambda = (x: Double) => x * x someLambda: Double => Double = $$Lambda$1277/1466120795@6fbd56da scala> mfun(0.0) res36: Double = 0.0 scala> mfun(2.0) res37: Double = 4.0 scala> mfun(5.0) res38: Double = 25.0
Point to static method:
//----- Point to java.lang.Math.cos static method ----------// // scala> mfun = java.lang.Math.cos mfun: MathFunc = $$Lambda$1078/2000449863@5abc5854 scala> mfun(pi) res2: Double = -0.9999999957076562 scala> mfun(Math.PI) res3: Double = -1.0 scala> mfun(Math.PI / 2.0) res4: Double = 6.123233995736766E-17 //------- Point to Math.log10 (Logarithm of base 10) -------// // scala> mfun = Math.log10 mfun: MathFunc = $$Lambda$1080/61227510@66487713 scala> mfun(1.0) res7: Double = 0.0 scala> mfun(10.0) res8: Double = 1.0 scala> mfun(100.0) res9: Double = 2.0
Point to instance method:
class LinFun(a: Double, b: Double){ private var _a: Double = a private var _b: Double = b def setA(a: Double) = _a = a def setB(b: Double) = _b = b def compute(x: Double): Double = _a * x + _b }
- Running:
scala> val linFun = new LinFun(3.0, 4.0) linFun: LinFun = LinFun@6f45872b scala> linFun.compute(0.0) res16: Double = 4.0 scala> linFun.compute(1.0) res17: Double = 7.0 scala> linFun.compute(2.0) res18: Double = 10.0 scala> mfun = linFun.compute mfun: MathFunc = $$Lambda$1247/485914296@501904ff scala> mfun(0.0) res21: Double = 4.0 scala> mfun(1.0) res22: Double = 7.0 scala> mfun(2.0) res23: Double = 10.0 // Compute now 2 * x + 0 //------------------------ scala> linFun.setA(2.0) scala> linFun.setB(0.0) scala> mfun(0.0) res27: Double = 0.0 scala> mfun(1.0) res28: Double = 2.0 scala> mfun(5.0) res29: Double = 10.0 scala> mfun.apply(0.0) res30: Double = 0.0 scala> mfun.apply(1.0) res31: Double = 2.0 scala> mfun.apply(3.0) res32: Double = 6.0
Decouple Classes
class TableBuilder{ private var _xmin: Double = 0; private var _xmax: Double = 10.0; private var _step: Double = 1.0; def setRange(xmin: Double, xmax: Double, step: Double = 0.1){ _xmin = xmin; _xmax = xmax; _step = step; println("Set xmin = {0} xmax = {1} step = {2} ", _xmin, _xmax, _step); } def show(fn: MathFunc) = for(x <- _xmin to _xmax by _step) println(f"x = $x%.3f\t y = ${fn(x)}%.3f") }
Running:
Note: The class TableBuilder does not need to know anything about the class linFun.
- Pass static method as argument
scala> tbl.show(Math.sin) x = 0.000 y = 0.000 x = 1.000 y = 0.841 x = 2.000 y = 0.909 x = 3.000 y = 0.141 x = 4.000 y = -0.757 x = 5.000 y = -0.959 x = 6.000 y = -0.279 x = 7.000 y = 0.657 x = 8.000 y = 0.989 x = 9.000 y = 0.412 x = 10.000 y = -0.544
- Pass instance method as argument
scala> val linFun = new LinFun(3.0, 4.0); linFun: LinFun = LinFun@27a65db7 // Note: Class TableBuilder does not need to know anything about class LinFun scala> tbl.show(linFun.compute) x = 0.000 y = 4.000 x = 1.000 y = 7.000 x = 2.000 y = 10.000 x = 3.000 y = 13.000 x = 4.000 y = 16.000 x = 5.000 y = 19.000 x = 6.000 y = 22.000 x = 7.000 y = 25.000 x = 8.000 y = 28.000 x = 9.000 y = 31.000 x = 10.000 y = 34.000 scala> linFun.setA(2.0) scala> linFun.setB(0.0) scala> tbl.show(linFun.compute) x = 0.000 y = 0.000 x = 1.000 y = 2.000 x = 2.000 y = 4.000 x = 3.000 y = 6.000 x = 4.000 y = 8.000 x = 5.000 y = 10.000 x = 6.000 y = 12.000 x = 7.000 y = 14.000 x = 8.000 y = 16.000 x = 9.000 y = 18.000 x = 10.000 y = 20.000
- Pass lambda function as argument
// Show constant function scala> tbl.show(x => 10.0) x = 0.000 y = 10.000 x = 1.000 y = 10.000 x = 2.000 y = 10.000 x = 3.000 y = 10.000 x = 4.000 y = 10.000 x = 5.000 y = 10.000 x = 6.000 y = 10.000 x = 7.000 y = 10.000 x = 8.000 y = 10.000 x = 9.000 y = 10.000 x = 10.000 y = 10.000
- Pass non compatible function as argument using lambda.
scala> def binFun(x: Double, y: Double) = 5 * x + 4 * y - 10.0 binFun: (x: Double, y: Double)Double scala> tbl.show(a => binFun(5.0, a)) x = 0.000 y = 15.000 x = 1.000 y = 19.000 x = 2.000 y = 23.000 x = 3.000 y = 27.000 x = 4.000 y = 31.000 x = 5.000 y = 35.000 x = 6.000 y = 39.000 x = 7.000 y = 43.000 x = 8.000 y = 47.000 x = 9.000 y = 51.000 x = 10.000 y = 55.000
1.6.3 Multicast Delegate
class MulticastDelegate[A]{ import scala.collection.mutable.ListBuffer private val _lst = new ListBuffer[A => Unit]() def :=(fn: A => Unit) = _lst.append(fn) def +=(fn: A => Unit) = _lst.append(fn) def apply(x: A) = for(fun <- _lst) fun(x) } // Singleton: Class of a single instance object Operations{ def add(x: Double, y: Double) = println(s"add(x = $x, y = $y) = ${x + y}") def mul(x: Double, y: Double) = println(s"mul(x = $x, y = $y) = ${x * y}") } val mt = new MulticastDelegate[(Double, Double)] // Acknowledgment: Thanks to the gits https://gist.github.com/jfrazee/6271143 scala> mt += (Operations.add _).tupled scala> mt += (Operations.mul _).tupled scala> mt += { case (x: Double, y: Double) => println("fn(x, y) = " + (3 * x + 4 * y))} scala> mt(4.0, 5.0) add(x = 4.0, y = 5.0) = 9.0 mul(x = 4.0, y = 5.0) = 20.0 fn(x, y) = 32.0 scala> mt.apply(3.0, 5.0) add(x = 3.0, y = 5.0) = 8.0 mul(x = 3.0, y = 5.0) = 15.0 fn(x, y) = 29.0 scala> val t = (4.0, 10.0) t: (Double, Double) = (4.0,10.0) scala> mt(t) add(x = 4.0, y = 10.0) = 14.0 mul(x = 4.0, y = 10.0) = 40.0 fn(x, y) = 52.0
1.6.4 References and further reading
- Delegates (C# Programming Guide) - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/
- A Delegate of simple numeric functions. - http://people.cs.aau.dk/~normark/oop-csharp/html/notes/more-operations-delegates1-note-program-1.html
- C# - Delegates - https://www.tutorialspoint.com/csharp/csharp_delegates.htm
- Dotnet-Perls - Delegate - https://www.dotnetperls.com/delegate
- Delegates and Events in C#/.NET - https://www.akadia.com/services/dotnet_delegates_and_events.html
- Microsft Developer - Delegates - http://kcshadow.net/wpdeveloper/?q=delegates
- When to Use Delegates Instead of Interfaces (C# Programming Guide)