-1

I would like to accomplish this:

A variable named abc must be None, except if the result of complicated treatments is true. I wrote a beginning of and answer but it doesn't work:

def abc={
None
copie.getRoot().asInstanceOf[DefaultMutableTreeNode].children() foreach ({
    site => <...more things after...>
} 

In the <more things after> you can find the result e.g. Some(site)

But the compiler does not accept this order, I mean "None" followed by some conditions eventually finishing by Some(xxx). And if I put "None" after the conditions, the result will always be "None" of course, and it's not what is expected.

Can you tell me if it can work this way, and how? Or otherwise how can I proceed?


@Robin:you saw right : I thought like if was in java : the result should be either None or Some(xxx),but amazingly if I put "None" at the beginning of the block and after "None" the conditional statements, which EVENTIUALLY return Some(xxx), eclipse's compiler does not accept my code. so the first question could be : is this order (None followed by some conditionnal treatments returning eventually Some(xxx) right? example:

def abc():Option[DefaultMutableTreeNode]={
    None
    MyTree.getRoot().children() foreach{site=>
        if (site.toBeImported()) Some(site)
            else site.children() foreach {type=>
                if (type.toBeImported()) Some(type)
        }
    }
}  

here this function returns None, Some(site) if a site is "toBeImported" (if many are, the last one will be returned), or Some(type) if a type is "toBeImported" (again the last one). This is not what I have in my program but it summaries well the idea.

bad_coder
  • 11,289
  • 20
  • 44
  • 72
lolveley
  • 1,659
  • 2
  • 18
  • 34
  • Why do you need that `None`? Anyway, your `abc` is of `Unit` return type, so you don't expect it to return nothing. What's the purpose of `abc`? – tkroman Aug 18 '13 at 14:55
  • 1
    @lolvely You are thinking in terms of the Java return keyword, which is a command which immediately stops execution of the current method. Scala's notion of return is "whatever value is obtained in the expression at the end of executing the function, is that function's return value". – Robin Green Aug 18 '13 at 17:36
  • @Robin:you saw right,but amazingly if I put "None" at the beginning of the block and after "None", the conditional statements, which EVENTIUALLY return Some(xxx), there is an error. Is this order right? e.g.: `def abc():Option[DefaultMutableTreeNode]={ None MyTree.getRoot().children() foreach{site=> if (site.toBeImported()) Some(site) else site.children() foreach {type=> if (type.toBeImported()) Some(type) } } }` – lolveley Aug 19 '13 at 12:43
  • @lolveley No, it is not right. The None is not at the _end_ of the function execution - it is not the expression that gets executed _last_ - so it has no effect. You can't do it that way! You have to return what you want to return from the _last_ expression to be executed. – Robin Green Aug 19 '13 at 13:18
  • @cdshines:yes,you're right; you should read : def abc():Option[Localisation]=... – lolveley Aug 19 '13 at 14:55
  • @robin:ok, I thought about it like a stack where results of code blocks are put, but it's wrong.I will have a travel at the scala documentation!thanks. – lolveley Aug 19 '13 at 14:58
  • Then use conditional statements. For example, you can do some operations on your `copie` and then, based on result, return that result or `None`. – tkroman Aug 19 '13 at 15:49

1 Answers1

1

I'm not sure that this is what you meant, but here's my try:

object CondSO extends App {
  def condition(site: String): Boolean = site.contains("flow")

  def complexCalc(db: List[String]) = db.filter(condition)

  // abc is not a variable (as addressed in original Q), but rather a method
  def abc(db: List[String]): Option[String] =
  // orig. Q was a bit confusing what result is - boolean or something else?
  // so, here it's returning a list of results
    complexCalc(db).headOption

  // second version - the "for" approach
  def abc2(db: List[String]): Option[String] = (
    for (site <- db if condition(site)) yield site
    ).headOption

  // third version - using return
  // probably fastest option. IMO other options could be
  // similarly fast if they would be rewritten to use stream
  // (they construct auxiliary list with all matching sites, not only first one)
  def abc3(db: List[String]): Option[String] = {
    for (site <- db if condition(site)) return Some(site)
    None
  }

  // last version - custom foreach
  implicit class IterablePimps[A](val i: Iterable[A]) {
    def foreachWithReturn[B](f: A => Option[B]): Option[B] = {
      while (i.iterator.hasNext)
        f(i.iterator.next()) match {
          case a: Some[B] => return a
          case _ =>
        }
      None
    }
  }

  def abc4(db: List[String]): Option[String] =
    db.foreachWithReturn(s => if (condition(s)) Some(s) else None)

  // testing section
  val dbs = Map[String, List[String]](
    "empty  " -> List(),
    "present" -> List("google.com", "stackoverflow.com"),
    "absent " -> List("root.cz", "abclinuxu.cz")
  )

  val funcs = Map[String, (List[String]) => Option[String]](
    "filter" -> abc,
    "for   " -> abc2,
    "return" -> abc3,
    "pimp  " -> abc4
  )

  for {
    db <- dbs
    f <- funcs
  } println(s"Applying ${f._1} on list ${db._1}: ${f._2(db._2)}")
}

Output:

Applying filter on list empty  : None
Applying for    on list empty  : None
Applying return on list empty  : None
Applying pimp   on list empty  : None
Applying filter on list present: Some(stackoverflow.com)
Applying for    on list present: Some(stackoverflow.com)
Applying return on list present: Some(stackoverflow.com)
Applying pimp   on list present: Some(stackoverflow.com)
Applying filter on list absent : None
Applying for    on list absent : None
Applying return on list absent : None
Applying pimp   on list absent : None

EDIT: modified methods to return one result, not a list in option. added more possible solutions (based on new information frmo questioner)

monnef
  • 3,903
  • 5
  • 30
  • 50