This document summarizes lessons learned from developing the Realm Android library. It discusses challenges such as setting up an Android library project, API design, testing, distribution methods, and issues like annotation processing, bytecode weaving, and native code support. Key points covered are how to start a library project, the importance of testing libraries extensively, and distribution options like Bintray.
This document summarizes a presentation about Packetbeat and monitoring distributed systems. It discusses how Packetbeat passively captures network packets, decodes protocols, and matches requests and responses to create JSON objects. It then sends this data to Elasticsearch for analysis. Aggregations like histograms, percentiles, and moving averages are used to analyze latency, identify slow methods, and detect anomalies in metrics over time. Other Beats like Topbeat, Filebeat, and Metricsbeat are also briefly introduced.
The document describes how to build a data science team and systems. It discusses establishing data collection and management systems, developing metrics and dashboards to analyze business data, creating predictive models using machine learning algorithms, and providing data science services like information retrieval to internal customers. The goal is to move from static, uncollected data to a fully realized big data platform and data science team that supports business analytics and decision making.
REEF is a meta-framework for big data analytics that eases development atop resource managers like YARN and Mesos. It provides a reusable control plane for coordinating data processing tasks and an adaptation layer for different resource managers. REEF decouples applications from cluster resources and handles common control plane functions like fault tolerance and configuration management. The framework is implemented in Java and C# and supports local, YARN, Mesos, and HDInsight execution environments. Future work includes graduating REEF from the Apache Incubator and using it to build new data processing frameworks and systems.
DRC-HUBO is Rainbow Robotics' humanoid robot that competed in the DRC Finals. It uses a modular, lightweight exoskeletal design with effective cooling and power systems. PODO-RT is the real-time framework that controls DRC-HUBO. It uses a distributed architecture with independent processes communicating over shared memory for high-speed control. DRC-HUBO demonstrated a variety of autonomous tasks at the DRC Finals, including driving, opening doors, using tools, and traversing rough terrain.
MIT researchers have developed highly efficient quadruped robots like the Cheetah that can run at speeds up to 6m/s. The Cheetah uses a proprioceptive actuation system with high torque density motors to achieve high force control bandwidth over 120Hz. Its parallelized control system with multicore CPUs and FPGAs allows control frequencies up to 4kHz. Design principles for efficient legged locomotion include energy regeneration, low transmission impedance, and low leg inertia. The researchers are continuing their work with robots like Cheetah 2 and Hermes.
This document discusses providing immersive sound for virtual reality. It notes that sound is half the experience of immersion. While VR technology allows immersion in digital worlds, truly immersive sound requires binaural 3D audio rendering or recording. Binaural audio uses head-related transfer functions to simulate the sound reaching each ear, allowing localization of sounds in 3D space. However, interactive binaural recording and matching sounds to visual content in real-time pose technical challenges. The document demonstrates an implementation of immersive 3D binaural audio for VR.
The document discusses various machine learning clustering algorithms like K-means clustering, DBSCAN, and EM clustering. It also discusses neural network architectures like LSTM, bi-LSTM, and convolutional neural networks. Finally, it presents results from evaluating different chatbot models on various metrics like validation score.
The document discusses challenges with using reinforcement learning for robotics. While simulations allow fast training of agents, there is often a "reality gap" when transferring learning to real robots. Other approaches like imitation learning and self-supervised learning can be safer alternatives that don't require trial-and-error. To better apply reinforcement learning, robots may need model-based approaches that learn forward models of the world, as well as techniques like active localization that allow robots to gather targeted information through interactive perception. Closing the reality gap will require finding ways to better match simulations to reality or allow robots to learn from real-world experiences.
[243] Deep Learning to help student’s Deep LearningNAVER D2
This document describes research on using deep learning to predict student performance in massive open online courses (MOOCs). It introduces GritNet, a model that takes raw student activity data as input and predicts outcomes like course graduation without feature engineering. GritNet outperforms baselines by more than 5% in predicting graduation. The document also describes how GritNet can be adapted in an unsupervised way to new courses using pseudo-labels, improving predictions in the first few weeks. Overall, GritNet is presented as the state-of-the-art for student prediction and can be transferred across courses without labels.
[234]Fast & Accurate Data Annotation Pipeline for AI applicationsNAVER D2
This document provides a summary of new datasets and papers related to computer vision tasks including object detection, image matting, person pose estimation, pedestrian detection, and person instance segmentation. A total of 8 papers and their associated datasets are listed with brief descriptions of the core contributions or techniques developed in each.
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지NAVER D2
This document presents a formula for calculating the loss function J(θ) in machine learning models. The formula averages the negative log likelihood of the predicted probabilities being correct over all samples S, and includes a regularization term λ that penalizes predicted embeddings being dissimilar from actual embeddings. It also defines the cosine similarity term used in the regularization.
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기NAVER D2
The document discusses running a TensorFlow Serving (TFS) container using Docker. It shows commands to:
1. Pull the TFS Docker image from a repository
2. Define a script to configure and run the TFS container, specifying the model path, name, and port mapping
3. Run the script to start the TFS container exposing port 13377
The document discusses linear algebra concepts including:
- Representing a system of linear equations as a matrix equation Ax = b where A is a coefficient matrix, x is a vector of unknowns, and b is a vector of constants.
- Solving for the vector x that satisfies the matrix equation using linear algebra techniques such as row reduction.
- Examples of matrix equations and their component vectors are shown.
This document describes the steps to convert a TensorFlow model to a TensorRT engine for inference. It includes steps to parse the model, optimize it, generate a runtime engine, serialize and deserialize the engine, as well as perform inference using the engine. It also provides code snippets for a PReLU plugin implementation in C++.
The document discusses machine reading comprehension (MRC) techniques for question answering (QA) systems, comparing search-based and natural language processing (NLP)-based approaches. It covers key milestones in the development of extractive QA models using NLP, from early sentence-level models to current state-of-the-art techniques like cross-attention, self-attention, and transfer learning. It notes the speed and scalability benefits of combining search and reading methods for QA.
8. 목차
•최근에 팬시앱에 들어간 메세징 구현을 따라가며 스위프트 기능 살펴보기
•옵셔널
•이뮤터블
•Guard
•Error Handling
9. 세션 소개
• 스위프트를 가볍게 소개해주는 세션은 아니지만 iOS 개발자가 매일 작성하는 뷰/모델/셀/
뷰컨트롤러단의 코드를 예로 들어 좋은 습관과 안 좋았던 습관, 어느정도 옵셔널을 써야하
는 가에 대한 고민, 코드를 좋게 만들기 위해 적용해 나갈 수 있는 기능들에 대한 소개와 모
나드에 대한 이해와 적용 그리고 부분적으로 스위프트 2.0에서 달라지는 예외처리나 패턴
매칭과 같은 기능도 다루려고 합니다
•모나드(flatMap) 제외. 죄송합니다
10. 메세지 기능
•FANCY 앱에 내장된 메세징 (고객과 셀러간의 커뮤니케이션)
•스티커, # 검색 같은거 없는 그냥 채팅
18. MessageViewController
새 대화: 기존 스레드가 없을 경우
그럼 targetUser 변수를 추가한다!
class MessageViewController: UIViewController {
var thread: MessageThread! //스레드가 있을 때 (기존 대화창)
var targetUser: MessageMember! //스레드가 없는데 새 상대랑 대화할 때
override func viewDidLoad() {
//스레드의 메세지들을 멋지게 보여준다
20. MessageViewController
targetUser는 다른 뷰(사용자 선택 뷰)를 통해 할당된다
func newMessage(sender: AnyObject) {
let selectUserViewController = SelectUserViewController() //사용자 선택 뷰
selectUserViewController.didSelect = { user in //선택하고 닫힐 때의 콜백
let messageViewController = MessageViewController()
messageViewController.targetUser = user //선택된 유저
navigationController?.pushViewController(messageViewController, animated: true)
}
presentViewController(selectUserViewController, animated: true, completion: nil)
}
21. MessageViewController
상호 배타적인 두 변수가 !
targetUser나 thread 둘 중 하나만 값이 있고 나머지는 nil이므로 그냥 옵셔널로 바꾸자
class MessageViewController: UIViewController {
var thread: MessageThread? //스레드가 있을 때 (기존 대화창)
var targetUser: MessageMember? //스레드가 없는데 새 상대랑 대화할 때
MessageViewController는 둘 중 하나만 있는 상황에 적절하게(?) 춤을 춘다
22. MessageViewController
옵셔널 댄스
춤의 예
override func viewDidLoad() {
// 뷰 타이틀 (스레드의 제목 혹은 사용자 이름)
title = thread?.title ?? (targetUser?.fullname ?? targetUser.username)
이런 코드가 도처에 난무할 것이다.
전송 때도 사용자ID 혹은 스레드ID를 선택적으로 보냄
if let t = thread { } , if let user = targetUser { }
23. MessageViewController
변수 선언 리뷰
class MessageViewController: UIViewController {
var thread: MessageThread? //스레드가 있을 때 (기존 대화창)
var targetUser: MessageMember? //스레드가 없는데 새 상대랑 대화할 때
이 선언은 맞는 것 같지만 우리가 원하는건 thread가 있거나 targetUser가 있는 양자 택일의
제약. 하지만 이 선언대로라면 둘다 nil이 될 수 있고 둘다 nil이 안될 수도 있음
30. iPad
iPad Message
• 빈 메세지 뷰를 보여주어야 함
• UISplitViewController를 처음 열때
• 혹은 메세지를 아카이브 했을 때
31. MessageViewController
진짜 둘다 nil
class MessageViewController: UIViewController {
var thread: MessageThread? //스레드가 있을 때 (기존 대화창)
var targetUser: MessageMember? //스레드가 없는데 새 상대랑 대화할 때
둘다 nil인 상황이 현실이 됨
이제 둘다 nil일 때도 처리해서 빈 화면을 보여주어야 함
33. MessageViewController
리팩토링
enum MessageViewMode {
case Thread(MessageThread)
case User(MessageMember)
case Empty
}
Enumeration (Associated Values): 연관된 값을 가질 수 있는 enum
//케이스 예
case MyCase(Int, String, Float?) //숫자, 문자열, 옵셔널 Float을 연관 타입으로 가지는 케이스
case MyAnotherCase(v1: Int, v2: NSError?) //Int, NSError? 타입의 네임드튜플을 가지는 케이스
34. MessageViewController
리팩토링: 생성자 오버라이딩, Non-Optional 변수
class MessageViewController: UIViewController {
var messageViewMode: MessageViewMode //옵셔널이 아님. nil이 될 수 없다
required init(coder aDecoder: NSCoder) {
fatalError("Not available")
}
init(mode: MessageViewMode) {
messageViewMode = mode
super.init(nibName: nil, bundle: nil)
}
}
35. MessageViewController
생성시
let vc = MessageViewController(mode: .Thread(thread)) //기존 스레드를 보여주는 모드
let vc = MessageViewController(mode: .User(member)) //새 사용자와 대화를 시작하는 모드
self.splitViewController?.showDetailViewController(
UINavigationController(rootViewController: MessageViewController(mode: .Empty))
//비어있는 모드
36. MessageViewController
제약 조건이 명확히 표현되었는가?
class MessageViewController: UIViewController {
var messageViewMode: MessageViewMode //옵셔널이 아니므로 모드가 꼭 있다
required init(coder aDecoder: NSCoder) {
fatalError("Not available")
}
init(mode: MessageViewMode) {
messageViewMode = mode //생성시 모드를 꼭 넘겨 받는다
super.init(nibName: nil, bundle: nil)
}
}
enum MessageViewMode {
case Thread(MessageThread) //옵셔널이 아니므로 nil일 수 없다
case User(MessageMember) //역시 옵셔널이 아니므로 nil일 수 없다
case Empty
}
37. MessageViewController
제약 조건 올킬
•메세지 뷰는 3가지 모드: 스레드 모드, 유저 모드, 비어있는 모드가 있다 (enum)
•이 3가지 모드 중 한 가지는 꼭 있어야 한다 (Non-optional과 init 오버라이딩)
•스레드 모드는 꼭 스레드 객체가 있어야 하며 다른 객체는 있을 수 없다
•유저 모드는 꼭 멤버 객체가 있어야 하며 다른 객체는 있을 수 없다
•비어있는 모드는 스레드 객체와 멤버 객체 둘 다 있을 수 없다
38. MessageViewController
하나 더: 왜 messageViewMode가 var일까?
class MessageViewController: UIViewController {
var messageViewMode: MessageViewMode //만약 이 뷰컨트롤러의 로직상 메세지 모드가 바뀔 수 있다면 var가 적합
class MessageViewController: UIViewController {
let messageViewMode: MessageViewMode //바뀔 수 없다는 걸 강제하고 싶다면 let
39. MessageViewController
Objective-C
typedef NS_ENUM(NSUInteger, MessageViewMode) {
MessageViewModeThread,
MessageViewModeTargetUser,
MessageViewModeEmpty,
}; //모드를 위한 enum을 만든다
@interface MessageViewController : UIViewController
@property (nonatomic, assign) MessageViewMode messageViewMode; //모드가 있지만
@property (nonatomic, strong) MessageThread *thread; //이 레퍼런스는 모드와 상충될 수 있다
@property (nonatomic, strong) MessageMember *targetUser; //마찬가지로 상충될 수 있다
@end
•NS_ENUM의 모드와 객체 변수와의 상관관계를 표현할 수 없다
41. MessageViewController
물론 더 구조화를 하면 어떻게든 할 수는 있겠지만.. 오버엔지니어링의 시작
@interface MessageViewMode : NSObject @end
@interface ThreadMode : MessageViewMode
@property (nonatomic, strong) MessageThread *thread;
@end
@interface TargetUserMode : MessageViewMode
@property (nonatomic, strong) MessageMember *targetUser;
@end
@interface MessageViewController : UIViewController
@property (nonatomic, strong) MessageViewMode *messageViewMode;
@end
42. 정리
개발자(김영후씨)의 의식 변화
•아 스레드 빨리 보여줘야지
•아 새 대화도 해야하네
•아 아이패드는 빈 화면도 있네
•아 막 여기저기서 메세지를 열어야 하네
•아 죽겠네
개발자의 머릿속에 있는 제약조건을 코드에 얼마나 표현 할 수 있는가?
그 표현을 위해 복잡도가 얼마나 증가하는가?
스위프트는 좋은 언어입니다
44. 옵셔널
다른 머글 언어의 레퍼런스 타입은 기본이 옵셔널
1. 스위프트는 반대로 기본 타입이 nil이 불가능하며 옵셔널 변수 선언을 ?나 !로 명시한다
2. !로 명시하면 옵셔널을 옵셔널이 아닌거 같이 쓰겠다는 만용
(저도 만용 많이 부립니다...)
45. 옵셔널
실제 코드
class SettingsHeaderView: UIView {
let logoImageView: UIImageView
let storeLabel: UILabel
let nameLabel: UILabel
let logoSize = 50.0
• 옵셔널이 아닌 변수가 의외로 많음
46. 옵셔널
옵셔널을 안쓰는 뷰 코드 템플릿
class MyView: UIView {
let myLabel: UILabel
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(frame: CGRect) {
myLabel = UILabel()
... //기타 UILabel 설정 (self에 접근하지 않는 설정들, 폰트, 색깔 등)
super.init(frame: frame)
//self가 필요한 설정 (이벤트 등)
addSubview(myLabel) //UITableViewCell이면 contentView.addSubview
}
}
47. 옵셔널
class ProductDetail: JSONModelProtocol { //Fancy Seller의 모델 코드
var productId: String?
var quantity: Int
var title: String
var description: String
var price: String
var numAvailable: Int
•이 경우 왜 ProductDetail의 productId는 옵셔널일까?
•앱에서 생성될 경우 서버와 싱크 되기 전까진 id 값이 없다
•즉 앱에서 생성될 수 있다는걸 productId를 따라가면 알 수 있음
49. 옵셔널
class ListViewController: UIViewController {
var headerView: UIView!
var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//headerView 초기화
//tableView 초기화
}
func anyFunction() {
tableView.reloadData() //옵셔널이 아닌것 처럼 사용
}
}
사실상 viewDidLoad부터 뷰 컨트롤러가 종료
될 때까지 nil이 아니라고 보증할 수 있기 때문
에 많이 사용되는 패턴
54. 이뮤터블 Immutability
무조건 / 생각없이 let부터 쓰는 습관
class ActivityTabView: UIView {
let activityButton: UIButton
let notificationButton: UIButton
let separator: UIView
•스위프트의 let은 객체의 프로퍼티 값이 변하는지에 관심이 없다
•오직 레퍼런스만 바뀌지 않으면 let
•즉 밸류 타입이 아닌 레퍼런스 타입은 대부분 let이 가능
55. 이뮤터블 Immutability
var가 보인다면
class MerchantCustomerDetail: MerchantCustomer {
let email: String
let isVip: Bool
let completedOrder: Int
let processingOrder: Int
let note: String
var orders:[MerchantOrder] = []
•var가 보인다면 이 타입이 밸류 타입이면서 값이 변하거나
•레퍼런스 타입이며 레퍼런스가 바뀐다는 아주 강력한 신호
56. 옵셔널과 이뮤터블
•현란한 테크닉 없이 이 둘만 꼼꼼히 챙겨도 상대적으로 좋은 코드 구현이 가능
•코드리딩시 옵셔널과 뮤터블 정보만 챙겨도 구현자의 주의점을 이해할 수 있음
•스위프트 2.0부턴 Xcode가 let을 더 잘 챙겨줌
57. 옵셔널 판단은 베팅
class FCMessageMember {
var memberId: NSNumber
init(dict: NSDictionary) {
memberId = dict.objectForKey("id") as! NSNumber //JSON에 id가 없다면 크래시
•옵셔널을 잘 못 판단하면 크래시가 날 수 있다
•코딩을 할 때 머릿속에서 어떤 가정을 해야하며 그 가정을 표현한다
•하지만 크래시는 피할 수 없다 Software is Hard
•그럼에도 옵셔널은 내가 어떤 가정을 했는지 알게 해주고
•잘못된 판단을 내렸을 경우 해당 문제를 확실히 이해하게 해준다
•그동안 얼마나 자주 문제를 이해하지 못하고 그저 null 체크만 추가했던가?
58. 모든 변수를 옵셔널(?, !)로 선언하면
베팅을 전혀 안한 것
스위프트를 안 쓰는 것과 다름 없다
60. 옵셔널을 이용하는 방법
tableView.tableFooterView?.hidden = true //nil이면 실행되지 않는다
tableView.tableFooterView?.addSubview(myView) //메소드 호출도 같은 방식
if let footerView = tableView.tableFooterView { //가장 일반화된 if-let
setupFooterInterface(footerView)
}
if let footerView = tableView.tableFooterView, let user = loggedInUser
where indexPath.section == 0 { //where에는 옵셔널과 상관없이 어떠한 조건문이든 올 수 있음
setupFooterInterface(footerView, forUser: user)
}
마지막 패턴은 충분히 강력하고 좋다 하지만...
61. 옵셔널을 이용하는 방법
if tableView.tableFooterView == nil || loggedInUser == nil {
//역으로 실패하는 조건문
return
}
setupFooterInterface(tableView.tableFooterView!, forUser: loggedInUser!)
•예외가 아닌 정상적인 흐름이 if let { 블록에 의해 브랜치 됨
•이렇게 할 경우 정상적인 흐름을 메인 브랜치에 둘 수 있지만 단점은 명백
•실패하는 조건문을 만들어야 하며
•옵셔널을 검사 하긴 했지만 바인딩 되지 않았으므로 !를 써야함
•스위프트가 아닌 머글 언어에서 흔히 보는 코드 ...
62. Guard (Swift 2.0)
guard let footerView = tableView.tableFooterView, let user = loggedInUser else {
//guard문이 실패할 경우
return
}
//여기서부터 이 guard문이 있는 블록에 footerView와 user 값이 바인딩되어 있음
setupFooterInterface(footerView, forUser: user)
•guard는 정상 구문과 옵셔널이 바인딩된 값을 메인 브랜치에서 사용 가능하게 해줌
•guard let <여기 오는 조건은 if let과 동일 (역이 아님)> else { 실패 경우 처리 }
64. Pattern Matching
switch (5, "Hello", 3.14) {
case (_, _ as String, let pi) where pi > 3.0: print("(pi)")
default: print("default")
}
•스위프트의 switch는 강력한 패턴 매칭을 지원함
•와일드카드 _ 패턴
•와일드카드 + 타입 체크 패턴 as String
•튜플의 3번째 요소를 let pi 바인딩
•where절로 패턴을 벗어난 모든 조건 검사
65. Pattern Matching
enum MerchantRouter: URLRequestConvertible {
case Order(orderId: String)
case OrderMarkAsProcessing(orderId: String)
case OrderFulfill(orderId: String, carrierCode: Int, tracking: String, items: String)
case OrderCancel(orderId: String)
case Products(filter: String, sort: String, ascending: String, search: String?,
cursor: APIPageCursor)
case Product(productId: String)
Enum, Associated Value로 더 강력하게 쓸 수 있다 (Alamofire)
클라이언트에서 URL 라우팅을 Enum으로 Type-safe하게 처리함
66. Pattern Matching
switch self {
case .Orders(let filter, let sort, let ascending, let search, _):
return ("/orders", ["filter": filter.0, "search": search, "sort[sort]": sort,
"sort[ascending]": ascending])
case .Order(let orderId):
return ("/orders/(orderId)", nil)
case .OrderMarkAsProcessing(let orderId):
return ("/orders/(orderId)", ["action": "mark_as_processing"])
URL 라우팅과 파라메터를 설정
빠진 Enum 케이스가 있을 경우 컴파일 경고
67. Pattern Matching
enum DownloadResult {
case Success(size: Int)
case Failure(description: String, code: Int)
}
if case .Failure(let message, let code) = result where code >= 400 {
print("Download Failure:(message)")
}
Swift 2.0부턴 switch가 아니어도 패턴 매칭 가능 if case
69. NSError
•Swift1.2까지의 에러 처리는 Objective-C의 패턴을 계승
•NSError ** 를 NSErrorPointer
•복원가능한(Recoverable) 에러에 한해 사용
var error: NSError? //꼭 옵셔널이어야 함
myString.writeToURL(url, atomically: true, encoding: NSUTF8StringEncoding, error: &error)
if let e = error {
println(e.localizedDescription)
}
70. NSException
•Objective-C에 있는 다른 언어의 예외 처리와 같은 @try { } @catch{ }
•복원 불가능한 에러, valueForKey:
@try {
[invocation invokeWithTarget:o];
}
@catch (NSException *exception) {
LogError(@"Exception during invocation: %@", exception);
}
•이것을 NSError 대신 못 쓸 이유는 없지만 프레임워크가 그럴 수 있도록 다양한 예외를 만
들어주지 않음
•NSFileSavingException 같은 예외를 만들어 주지 않고 NSError를 사용
72. Swift 2.0 Error Handling
•에러 핸들링
do {
try myString.writeToURL(url, atomically: true, encoding: NSUTF8StringEncoding)
} catch let error as NSError {
print(error.localizedDescription)
}
•do, catch 블록
•throw 마크가 된 함수를 호출 할 때 try를 붙여야 함
•do 내에서 throw�� 있는 호출은 다 try를 붙여야 함
•Java와 달리 어떤 호출이 예외를 발생시키는지를 명확히 함. try { }로 퉁칠 수 없다!
73. ErrorType
•ErrorType 프로토콜을 사용해서 Enum으로 에러를 정의 가능
enum MyGameError: ErrorType {
case Bad(String)
case Worse(Int)
case Terrible
}
func doDangerousStuff() throws {
//위험한 작업을 한다
throw MyGameError.Bad("OMG") //예외 발생
}
do {
try doDangerousStuff()
} catch MyGameError.Bad(let message) {
print(message)
}
•스위프트 2.0이 보편화 되면 많은 API가
NSError대신 Enum을 사용할 것
74. ErrorType + Guard
•Guard는 에러 핸들링에 아주 적합함
enum ProductError: ErrorType {
case InputMissing
case Quantity(Int)
case Other(String)
}
func createProduct() throws {
guard let title = titleField.text, quantity = quantityField.text
where !title.isEmpty && !quantity.isEmpty else {
throw ProductError.InputMissing
}
guard let quantityNumber = Int(quantity) where quantityNumber > 10 else {
throw ProductError.Quantity(quantityNumber)
}
//create product
}
75. ErrorType + Pattern Matching
•Catch는 switch나 if case처럼 패턴 매칭이 가능
do {
try createProduct()
} catch ProductError.InputMissing {
print("Input Missing")
} catch ProductError.Quantity(let minimum) {
print("Quantity Minimum:(minimum)")
}
76. Defer
•try-catch-finally?
do {
defer {
//finally
print("release resource")
}
try myString.writeToURL(url, atomically: true, encoding: NSUTF8StringEncoding)
} catch let error as NSError {
print(error.localizedDescription)
}
•defer는 해당 블록(func, do 등)이 마지막에 무조건 호출 됨
•에러 처리를 떠나 보편적인 응용 가능성이 높음
77. 새로 스위프트 프로젝트를 시작한다면...
•Fancy Seller
•AFNetworking 대신 Alamofire
•JSON처리에 NSDictionary대신 SwiftyJSON
•2.0에서 강화된 프로토콜과 제네릭을 이용해서 MVVM 구조를 가지도록 노력해 봤을 것
•Guard와 ErrorType을 이용해서 예외처리를 좀 더 제대로 설계 했을 것
81. Optional
map
let numbers = [1, 2, 3]
let n = numbers.map { $0 * 2 }
•Array에 대한 map은 이제 너무나 당연한 이디엄이 됨
•하지만 옵셔널도 map이 됨
var number: Int? = 5
var newNumber: Int? = number.map { $0 * 5 }
•이렇게 map 연산을 지원하는 타입(어레이, 옵셔널 등)을 Functor라고 부름
84. flatMap
숫자값을 가지고 있는 String을 가격 포매팅을 해보자
근데 ,가 아닌 .로 바꿔보자
“5000” -> Some(“5.000”)
“ABC” -> nil
85. flatMap
숫자값을 가지고 있는 String을 가격 포매팅을 해보자
•문자를 숫자로 변환(NSNumberFormatter의 numberFromString)
= String -> NSNumber?
•숫자를 가격 문자로 변환 (NSNumberFormatter의 stringFromNumber)
= NSNumber -> String?
•다시 문자를 문자로 변환
= String -> String?
86. flatMap
숫자값을 가지고 있는 String을 가격 포매팅을 해보자
let f1: NSNumberFormatter = … //문자->숫자? 포매터
let f2: NSNumberFormatter = … //숫자->문자? 포매터, NSNumberFormatterStyle.CurrencyStyle 사용
extension String {
public func priceAsDecimal() -> String? {
return f1.numberFromString(self).flatMap { f2.stringFromNumber($0) }
}
}
•값을 받아 박스(옵셔널)를 돌려주는 함수의 무한한 결합을1차원으로 만들 수 있음
•String -> NSNumber?, NSNumber -> String?
87. flatMap
왜 map은 안되나
extension String {
public func priceAsDecimal() -> String?? {
return f1.numberFromString(self).map { f2.stringFromNumber($0) }
}
}
•stringFromNumber가 String?을 돌려준다
•map은 계산된 값을 다시 박스(옵셔널)에 감싼다 (어레이의 map도 동일)
•즉 map을 쓰면 String?? = Optional<Optional<String>>이 되어 불가능
•flatMap이라고 부르는 이유
88. flatMap
숫자값을 가지고 있는 String을 가격 포매팅을 해보자
func replaceComma(s: String) -> String? {
...
}
public func priceAsDecimal() -> String? {
return f1.numberFromString(self).flatMap { f2.stringFromNumber($0) }.flatMap(replaceComma)
}
•값을 받아 박스(옵셔널)를 돌려주는 함수의 무한한 결합을1차원으로 만들 수 있음
•String -> NSNumber?, NSNumber -> String?, String -> String?
89. flatMap
if let을 쓴다면
public func priceAsDecimal2() -> String? { //스위프트 1.0
if let n = f1.numberFromString(self) {
if let p = f2.stringFromNumber(n) {
return replaceComma(p)
}
}
return nil
}
90. flatMap
if let을 쓴다면
public func priceAsDecimal2() -> String? { //스위프트 1.2
if let n = f1.numberFromString(self), p = f2.stringFromNumber(n) {
return replaceComma(p)
}
return nil
}
•1.2의 if let은 flatMap처럼 의존성 있는 옵셔널 바인딩들을 1차원으로 만들 수 있음
•if let이 옵셔널에 대한 flatMap을 문법으로 만들었다고 볼 수 있음
•그럼 왜 쓰나 flatMap ...
91. flatMap
let title = NSURL(string:”http://“).flatMap { NSData(contentsOfURL: $0)}?.flatMap {
NSJSONSerialization.JSONObjectWithData($0, options: NSJSONReadingOptions(0)) as? NSDictionary}.flatMap {
$0["title"] as? String
}
if let url = NSURL(string: "http://"), data = NSData(contentsOfURL: url),
json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: nil) as?
NSDictionary {
title = $0["title"] as? String
}
flatMap vs if let
92. flatMap
•flatMap은 제네릭 패턴 (if let은 옵셔널에 한정): 어레이도 flatMap이 있음
•타입A를 받고 무언가로 감싼A를 돌려주는 함수 패턴을 결합 가능
•함수를 A->B? 식으로 설계하면 flatMap으로 연계 가능
•flatMap은 모나드 연산자 >>= 이며 flatMap을 지원하는 타입을 모나드 라고 부름
•즉 스위프트의 옵셔널과 어레이는 모나드
•다른 추상 타입도 flatMap 연산을 만들면 모나드
•더 공부해 봅시다