3

Can you explain me :

1) In PermSet , in line where val u initialized: why it possible to write "file.u= _ " ? file._u I can understand, but not the rest...

2)

perms:(Perm => Unit, () => Perm)* - what does it mean?

case class PermSet(file:FilePerms, perms:(Perm => Unit, () => Perm)* ) {

}



object PermSet {
    val u   =  (file:FilePerms) => new PermSet(file,(file._u_= _ , file._u _))
    val g   =  (file:FilePerms) => new PermSet(file,(file._g_= _ , file._g _))
    val o   =  (file:FilePerms) => new PermSet(file,(file._o_= _ , file._o _))
    ...
}



class FilePerms(
   var _u:Perm=none,
   var _g:Perm=none,
   var _o:Perm=none
) {
   ...
  }
Stefano Sanfilippo
  • 32,265
  • 7
  • 79
  • 80
Vladimir Nabokov
  • 1,797
  • 1
  • 14
  • 19

3 Answers3

2

2) perms:(Perm => Unit, () => Perm)*:

  • a star * symbol means that function takes a variable number of arguments of this type.
  • The (X, Y) form is a pair or Tuple2[+T1, +T2].
  • Perm => Unit means that you need to pass a function that takes a Perm argument and returns Unit - basically returns nothing, so it most likely doing side effecting. Similarly () => Perm means that it expects a function with no args that returns a Perm.

1) Underscore _ is a placeholder - a variable will be placed in there when the function is called. So if you have this syntax file._u_= _ then it means that some value will placed on the right side of = in place of _ when this code is called and then assigned to file._u. Assignment does not return anything, i.e Unit.

yǝsʞǝla
  • 16,272
  • 2
  • 44
  • 65
2

The compiler automatically generates a getter and setter for each class property.

class FilePerms {
    var _u:Perm=none
}

in essence becomes

class FilePerms {
    private var __u:Perm=none

    // Getter
    def _u = __u

    // Setter
    def _u_=(v:Perm) {
        __u = v
    }
}

So file._u_= is the setter for the _u property.

When you want to access a method as an object, you add an underscore after it.

If you want to pass the setter to another method or constructor, you would say

file._u_= _
bwroga
  • 5,379
  • 2
  • 23
  • 25
2

The technical part

case class PermSet(file:FilePerms, perms:(Perm => Unit, () => Perm)* )

Is a case class that receives a concrete FilePerms instance as well as s variable numbers (0 or more) of perms.

Each perm is a Tuple of functions.

The first function of the pair (Perm => Unit) receives a Perm and does not return anything (Unit) - if you are a c or java guy, read Unit as void. So, the main use of this function should be mutating a Perm (a mutator aka setter).

The second function of the pair (() => Perm) is a function with no arguments that returns a Perm (looks like an accessor, aka getter).

Now for

val u = (file:FilePerms) => new PermSet(file, (file._u_= _ , file._u _))

u is a function that receives some concrete FilePerms and create a PermSet out of it.

  • (file._u_= _ , file._u _) is a Tuple
  • file._u_= _ is a function that respects the defined contract for the first type of the Tuple (Perm => Unit)
  • file._u _ is also a function that respects the defined contract for the second type argument of the Tuple (() => Perm)

On file._u_=, u_= is an mutator method on file (an instance of FilePerms). The mutator receives a Perm, stores it in file and returns nothing (Unit). The trailing _ is a magical conversion operator that lets the setter method on FilePerms behave as a function (Perm => Unit)

In the same way, on file._u _, _u is a accessor method with no arguments (()) that returns a Perm (from file). Again _ triggers a conversion where the accessor method gets expanded as a function (() => Perm).

If the difference between method and function is becoming foggy, specially with all of those vals around. Read this answer from Daniel Sobral.

The conceptual part

This code is doing the following:

Declaring user (u), group (g) and other (u) instance permissions (FilePerms). Think of this class as the concrete permissions of a specific file or directory.

Declaring a case class PermSet that receives a instance of FilePerms and zero or more perms, which are nothing more than a Tuple of functions that can mutate and access a permission. The purpose of this class is to wrap instance permissions in a way to expose only permissions that you want someone to be able to access and or mutate. The hidden conceptual key word here is grant. The file have permissions FilePerms, of those, you can filter the ones that should be exposed using a PermSet.

Finally, PermSet companion object is declaring some permissions (u, g, o) (think of them as Java static methods), each one will receive a instance of FilePerms and return a PermSet capable of mutating and accessing that particular permission. So think of them as static methods capable of extracting default PermSets out of FileSet. E.g. u(myFile) will return a PermSet able to access and manipulate myFile user permissions.

Community
  • 1
  • 1
Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118