scala에서 json4s를 간단하게 사용할 때, Map[String, Any]으로 파싱할 때 특별히 에러가 발생하지 않는다.


간단히 동작하는 예시는 다음과 같다. 



import
org.json4s._
import org.json4s.JsonAST.{JObject, JValue}
import org.json4s.jackson.{Json, JsonMethods}

implicit val formats = DefaultFormats
val source = """{"comment_type":"general"}"""
val commentType = JsonMethods.parse(source) .extract[Map[String, Any]].get("comment_type")
println(commentType)



하지만, Spark에서 사용하면 에러가 발생한다. 


org.json4s.package$MappingException: No usable value for... 




이런 비슷한 얘기가 json4s 이슈에 있다. 

https://github.com/json4s/json4s/issues/124




그래서 Map이 아닌 case class를 사용하면 또 에러가 발생한다. 


기본 값을 넣어줘야 에러가 발생하지 않는다. 



case class Comment(comment_type: String = "general")


좀 더 고급스럽게 Option을 추가한다.


case class Comment(comment_type: Option[String] = Some("general"))



 잘 동작한다. Map 대신 case class를 사용하기를 추천한다. 


import org.json4s._
import org.json4s.JsonAST.{JObject, JValue}
import org.json4s.jackson.{Json, JsonMethods}

case class Comment(comment_type: Option[String] = Some("general"))

implicit val formats = DefaultFormats
val source = """{"comment_type":"general"}"""
val commentType = JsonMethods.parse(source).extract[Comment].comment_type
println(commentType)



Spark에서 이렇게 쓰면 아주 잘 작동할 것 같았지만, 이슈가 있다. 다른 필드 파싱할 때, 예상되는 타입과 실제 값과의 차이로 파싱 에러가 발생할 수 있다.



이럴 때는 Try문를 추가하고, Comment에 해당되는 모든 필드에 대해서 Option 처리를 추가해야 한다. 어떤 값과 상관없이 처리할 수 있도록 해야 한다.


case class Comment(comment_type: Option[String] = Some("general"), action: Option[String] = Some("create", ....)

Posted by '김용환'
,


scala의 json4s 사용시 아래와 같은 에러가 발생하면, 필드에 대한 오타가 발생했다.



Exception in thread "main" org.json4s.package$MappingException: No usable value for xxx

Did not find value which can be converted into java.lang.String


예를 들어, json source의 내용의 comment_type이고, case class은 comments_type으로 잘못 매핑 구조를 만들면, 에러가 발생한다. 



예)


val source = """{"comment_type":"general"}"""



case class Comment(comments_type: String)

JsonMethods.parse(source).extract[Comment].comment_type


Posted by '김용환'
,




참고 : http://www.artima.com/articles/dci_vision.html


객체는 폴리모피즘, 커플링, 응집도가 아니라, 사람들과 사람들의 멘탈 모델에 대한 내용이다. 


MVC는 멘탈 모델이지 관찰자 패턴이 아니다.












참고 http://dm-academy.github.io/aitm/aitm-instructor.html


In this situation, each person has their own “mental model” of what needs to be done, and their own tracking mechanism. We don’t know how the work is being transmitted: emails, phone calls, hallway conversations (”Say Sara, there is an issue with Customer X’s bill, can you please look into it?”)







참고 : http://designbyforest.tistory.com/entry/UX%EB%AA%A8%EB%93%A0-%EA%B8%B0%ED%9A%8D%EC%9E%90%EC%99%80-%EB%94%94%EC%9E%90%EC%9D%B4%EB%84%88%EA%B0%80-%EC%95%8C%EC%95%84%EC%95%BC-%ED%95%A0-%EC%82%AC%EB%9E%8C%EC%97%90-%EB%8C%80%ED%95%9C-100%EA%B0%80%EC%A7%80%EC%82%AC%EC%8B%A4



03 사람들은 패턴 인식을 통해 사물을 인식한다.
-사람은 자동적으로 패턴을 찾음. 분류와 공백을 이용 패턴을 만들어 내는것이 좋음.
-아이콘 요소는 인지하게 만드는게 쉽고, 빠르게 인지하게 함.
-평면보다는 입체를 더 잘 인지. 단, 화면상에  표현된 입체 요소를 인지하고 이해하는 속도는 평면 요소에 비해 느릴수도 있음.


멘탈모델이란?
실세계의 특정 대상물이 어떻게 작동하는지에 대한 사람의 사고 과정에 대한 설명.
디자인 모델 - 디자이너의 개념모델을 말함.
사용자 모델 - 사용자가가 시스템과 상호 작용하는 과정에서 만들어낸 멘탈모델을 말함.


28 특정 유형의 인지 처리 과정은 더욱 까다롭다.
- 디자인할 때 사용자가 많이 생각하거나 기억하지 않아도 되게 한다. 이 두 가지는 인지 부하를 일으켜 많은 정신적 자원을 필요로 한다.
- 기회 비용에 대해 고민하라. 예를 들어 시각 부하나 운동 부하를 높여 인지 부하를 줄일 수 있는 곳이 있다.
- 사람이 선택하는 항목을 충분히 키워서 쉽게 도달할 수 있게 만든다.







참고 : http://egloos.zum.com/hisprite/v/3810333


멘탈모델은 
일. 서비스나 제품 기획에 지침이 될 수 있고
이. 사용자와 사업을 위해서 좋은의사결정을 내리도록 도와주며
삼. 장기적인 비전과 기회를 제시해 준다.







참고 : http://blog.naver.com/PostView.nhn?blogId=vinylx&logNo=220171087380&redirect=Dlog&widgetTypeCall=true


정의 및 가치

멘탈 모델의 활용 가치는 발생할 수 있는 문제점을 미리 파악하고, 통합적인 서비스 이해를 바탕으로 해결 방안을 도출할 수 있다는 데 있습니다. 이 모델은 이전 포스트에서 소개된 ‘친화도 맵’이라고도 불리는 ‘어피니티 다이어그램(Affinity Diagram) - 사용자의 공통된 행동자료를 의미상 가까운 것끼리 모아 놓은 다이어그램’과도 밀접한 관련이 있습니다. 즉, 다른 사람의 행동 동기, 사고 과정을 비롯한 감성적, 철학적 배경을 이해하기 위하여 그들과 대화하고, 행동 패턴을 도출하여 정리한 것이 ‘멘탈 모델’ 입니다. 여기서는 ‘행동(task)’이라는 단어는 행위, 생각, 기분, 철학 그리고 동기에 이르기까지 사람이 무언가를 이루거나, 무언가를 움직이거나, 특정한 상태에 이를 때 나타나는 모든 것을 포괄하는 의미로 정의하도록 하겠습니다.













Posted by '김용환'
,




json4s를 spark에 쓸 때, 버전 관리를 잘 해야 한다. scala 1.5.x, 1.6.x은 json4s의 3.2.x만 사용할 수 있다.

그 이상의 버전을 사용하면, java.lang.NoSuchMethodError: org.json4s.jackson.JsonMethods$.parse$default$3()Z 예외가 발생한다.





https://github.com/json4s/json4s/issues/316


Spark 1.5.0 depends on json4s 3.2.10. json4s 3.2.10 and 3.3.0 does not have binary compatibility. You can't use spark 1.5.0 and json4s 3.3.0 together.

Posted by '김용환'
,

[scala] json 이슈

scala 2016. 10. 12. 19:18




1) play-js




2) json4s


scala json 라이브러리 중 하나인 json4s 3.2~3.4를 사용하고 있다.


  val json = parse(""" { "type": "general", "name":"sticon"} """)


json.extract[Map[String, Any]]로 호출할 때, No information known about type at ... Exception이 난다.


원인은 library 버전 의존성 또는 library 이슈로 생각된다.



https://github.com/json4s/json4s/issues/124




3) pickling


https://github.com/scala/pickling

Posted by '김용환'
,


참조

http://rubykr.github.io/rails_guides/getting_started.html




ruby on rails 애플리케이션을 실행하려면 다음 절차를 가진다.


1. 외부 라이브러러를 다운받는다.


$ bundle install 



2. 기타 유틸리를 확인해서 설치한다. 

yum 또는 brew를 사용한다.


$ brew install cronolog

(실행 중에 3단계에서 http 요청을 제대로 못할 경우..)



3. rails server



4. 브라우져 실행


 http://localhost:3000/

 http://localhost:3000/uri

Posted by '김용환'
,

 flatMap은 filter+map의 역할을 할 수 있다. 


filter를 먼저하고, map을 하는 일반적인 코딩이다.

val list = List(1,2,3,4,5,6,7,8,9,10)
val result = list.filter(
x => 0 == (x % 2)
).map(
x => x + 1
)

println(result)

결과는 다음과 같다. 


List(3, 5, 7, 9, 11)




flatMap과 if문으로 변환하면 다음과 같다. 

val flatMapResult = list.flatMap(x =>
if (0 == (x % 2)) {
Some(x+1)
} else {
None
}
)

println(flatMapResult)


결과는 위와 동일하고, 훨씬 깔끔한 느낌이다.




List(3, 5, 7, 9, 11)





filter->map을 쓰는 조합에서 flatMap으로 바꿔야 했던 사례가 있었다.


Spark으로 대용량 처리하던 중, 

filter에서 사용하고, map에서도 사용해야 하는 중복 코드가 발생할 수 있는데, 이를 깔끔하게 중복처리하지 않으려면, flatMap을 사용하면 중복 코드가 발생하지 않는다. 






Posted by '김용환'
,


scala는 groupBy api를 제공한다. 정확히 말하면, TraserableLike.groupBy을 사용할 수 있다.


println("java scala".trim.groupBy(identity))



identity는 정의된 함수를 사용하여 단어별로 groupBy를 할 수 있다.

def identity[A](x: A): A = x// @see `conforms` for the implicit version


groupBy 결과는 다음과 같다.


Map(s -> s, j -> j, a -> aaaa,   ->  , v -> v, l -> l, c -> c)



카운트를 계산하기 위해서는 mapValues를 이용해 본다. 



println("java scala".trim.groupBy(identity).mapValues(_.size).toVector)

결과는 다음과 같다.


Vector((s,1), (j,1), (a,4), ( ,1), (v,1), (l,1), (c,1))





3 개의 값을 가진 튜플에 대해서 groupBy를 호출한다. 

val list = Seq(("one", "i", "char"), ("two", "2", "num"), ("two", "ii", "char"), ("one", "1", "num"), ("four", "iv", "char"), ("five", "iv", "char"))


val v = list.groupBy(_._3)
println(v)

val values = list.groupBy(_._3).mapValues(_.map(_._2))
println(values)



첫 번째 groupBy 결과는 다음과 같다.


Map(num -> List((two,2,num), (one,1,num)), char -> List((one,i,char), (two,ii,char), (four,iv,char), (five,iv,char)))



두 번째 groupBy-mapValues 결과는 다음과 같다.


Map(num -> List(2, 1), char -> List(i, ii, iv, iv))





키 별 개수를 알고 싶다면, 다음과 같은 코드를 사용할 수 있다.


val values1 = list.groupBy(_._3).map(t => (t._1, t._2.length))
println(values1)



Map(num -> 2, char -> 4)




Posted by '김용환'
,



lazy evaluation이 왜 빠른지 궁금할 때 보면 좋을 만한 자료가 있다.


참조

http://filimanjaro.com/blog/2014/introducing-lazy-evaluation/



strict evaluation(eagerly evalution)의 방법은 한 단계씩 차례차례 진행한다고 할 수 있다.




lazy evaluation은 한 번에 처리를 한다는 개념(마치 chunk 배치) 으로 보면 된다.



따라서 대부분의 경우는 이렇게 성능이 좋다.!!








전체적으로 lazy 방식이 성능이 좋다. 



하지만, 항상(무조건) 빠르다고 보장할 수는 없다. 대충 비슷할 수도 있기 때문에 테스트가 필요하다.



또한, 코드는 복잡해지기 때문에 유지보수성이 떨어질 수 있는 단점이 있다. 





view를 이용해 lazy와 eager 계산법으로 만든 예시를 소개한다.



val list = List(0, 1, 2, 3, 4, 5)
// eager evaluation : 조급한 계산법 (위키)
val evens = list.map(i => {
println(s"$i")
i + 10
}).filter(i => {
i % 2 == 0
}).take(2).foreach(println)

println("-------")

// view를 이용한 lazy evaluation : 느긋한 계산법 (위키)
val evensView = list.view.map(i => {
println(s"$i")
i + 30
}).filter(i => {
i % 2 == 0
}).take(2).foreach(println)

첫 번째 stream(eager)에 대한 결과는 다음과 같다.


0

1

2

3

4

5

10

12



두 번째 stream(view를 사용한 lazy) 결과는 다음과 같다.



0

30

1

2

32



첫 번째 stream은 list의 모든 엘리먼트를 조사하고 결과를 내지만,

두 번째 stream은 정확하게 필요한 내용만 조사하기 때문에 속도가 빠르다. 

Posted by '김용환'
,

[scala] retry

scala 2016. 10. 6. 19:20

spring4에서는 Retryable을 사용하면 retry 관련 코드가 짧아진다.


 @Retryable(maxAttempts = 2, backoff = @Backoff(delay = 0))
String call(String url);




scala에서는 아예 쉽게 retry를 쉽게 만들 수 있다. 


아래 링크를 참조하면 좋은 결과를 얻을 수 있다. 꼬리 재귀와 커링을 사용했다. 


http://stackoverflow.com/questions/7930814/whats-the-scala-way-to-implement-a-retry-able-call-like-this-one



object Main extends App {
@annotation.tailrec
def retry[T](n: Int)(fn: => T): T = {
util.Try { fn } match {
case util.Success(x) => x
case _ if n > 1 => retry(n - 1)(fn)
case util.Failure(e) => throw e
}
}

var i = 0;
retry(3) {
i += 1
test(i)
}

def test(i: Int): Unit = {
if (i == 1 || i == 2) throw new Exception("XXX")
if (i == 3) {
System.out.println(i)
}
}
}


결과는 3이다. 








Posted by '김용환'
,