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
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
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()
...
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)
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
...
- 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")
- 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) }
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)
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")
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()))
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"
}
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
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>
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
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
- 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)